IM/backend/IM_API/Services/FriendService.cs
nanxun 58bc8b4b5a 前端:
1、优化消息排序逻辑
2、新增加载历史消息
3、修复已知问题
后端:
1、优化消息排序逻辑
2、增加用户信息缓存机制
3、修改日期类型为DateTimeOffset改善时区信息丢失问题
3、修复了已知问题
数据库:
1、新增SequenceId字段用于消息排序
2、新增ClientMsgId字段用于客户端消息回执
2026-02-07 22:37:56 +08:00

221 lines
9.7 KiB
C#

using AutoMapper;
using IM_API.Domain.Events;
using IM_API.Dtos.Friend;
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
{
public class FriendService : IFriendSerivce
{
private readonly ImContext _context;
private readonly ILogger<FriendService> _logger;
private readonly 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)
{
var friend = await _context.Friends.FirstOrDefaultAsync(x => x.Id == friendId);
if (friend == null) throw new BaseException(CodeDefine.FRIEND_RELATION_NOT_FOUND);
friend.StatusEnum = FriendStatus.Blocked;
await _context.SaveChangesAsync();
return true;
}
#endregion
#region id拉黑好友
public async Task<bool> BlockFriendByUserIdAsync(int userId, int toUserId)
{
var friend = await _context.Friends.FirstOrDefaultAsync(x => x.UserId == userId && x.FriendId == toUserId);
if (friend == null) throw new BaseException(CodeDefine.FRIEND_RELATION_NOT_FOUND);
friend.StatusEnum = FriendStatus.Blocked;
await _context.SaveChangesAsync();
return true;
}
#endregion
#region
public async Task<bool> DeleteFriendAsync(int friendId)
{
var friend = await _context.Friends.FirstOrDefaultAsync(x => x.Id == friendId);
if (friend is null) throw new BaseException(CodeDefine.FRIEND_RELATION_NOT_FOUND);
_context.Friends.Remove(friend);
await _context.SaveChangesAsync();
return true;
}
#endregion
#region id删除好友关系
public async Task<bool> DeleteFriendByUserIdAsync(int userId, int toUserId)
{
var friend = await _context.Friends.FirstOrDefaultAsync(x => x.UserId == userId && x.FriendId == toUserId);
if (friend is null) throw new BaseException(CodeDefine.FRIEND_RELATION_NOT_FOUND);
_context.Friends.Remove(friend);
await _context.SaveChangesAsync();
return true;
}
#endregion
#region
public async Task<List<FriendInfoDto>> GetFriendListAsync(int userId, int page, int limit, bool desc)
{
var query = _context.Friends.Include(u => u.FriendNavigation).Where(x => x.UserId == userId && x.Status == (sbyte)FriendStatus.Added);
if (desc)
{
query = query.OrderByDescending(x => x.UserId);
}
var friendList = await query.Skip(((page - 1) * limit)).Take(limit).ToListAsync();
return _mapper.Map<List<FriendInfoDto>>(friendList);
}
#endregion
#region
public async Task<List<FriendRequestResDto>> GetFriendRequestListAsync(int userId, int page, int limit, bool desc)
{
var query = _context.FriendRequests
.Include(x => x.ResponseUserNavigation)
.Include(x => x.RequestUserNavigation)
.Where(
x => (x.ResponseUser == userId) ||
x.RequestUser == userId
)
.Select(s => new FriendRequestResDto
{
Id = s.Id,
RequestUser = s.RequestUser,
ResponseUser = s.ResponseUser,
Avatar = s.RequestUser == userId ? s.ResponseUserNavigation.Avatar : s.RequestUserNavigation.Avatar,
Created = s.Created,
NickName = s.RequestUser == userId ? s.ResponseUserNavigation.NickName : s.RequestUserNavigation.NickName,
Description = s.Description,
State = (FriendRequestState)s.State
})
;
query = query.OrderByDescending(x => x.Id);
var friendRequestList = await query.Skip(((page - 1) * limit)).Take(limit).ToListAsync();
return friendRequestList;
}
#endregion
#region
public async Task<bool> HandleFriendRequestAsync(HandleFriendRequestDto requestDto)
{
//查询好友请求记录
var friendRequest = await _context.FriendRequests
.Include(e => e.ResponseUserNavigation)
.FirstOrDefaultAsync(x => x.Id == requestDto.RequestId);
if (friendRequest is null) throw new BaseException(CodeDefine.FRIEND_REQUEST_NOT_FOUND);
//查询好友关系
var friend = await _context.Friends.FirstOrDefaultAsync(
x => x.UserId == friendRequest.RequestUser && x.FriendId == friendRequest.ResponseUser
);
if (friend != null) throw new BaseException(CodeDefine.ALREADY_FRIENDS);
//处理好友请求操作
switch (requestDto.Action)
{
//拒绝后标记
case HandleFriendRequestAction.Reject:
friendRequest.StateEnum = FriendRequestState.Declined;
break;
//同意后标记
case HandleFriendRequestAction.Accept:
friendRequest.StateEnum = FriendRequestState.Passed;
await _endpoint.Publish(new FriendAddEvent()
{
AggregateId = friendRequest.Id.ToString(),
OccurredAt = DateTime.Now,
Created = DateTime.Now,
EventId = Guid.NewGuid(),
OperatorId = friendRequest.ResponseUser,
RequestInfo = _mapper.Map<FriendRequestDto>(friendRequest),
requestUserRemarkname = requestDto.RemarkName,
RequestUserId = friendRequest.RequestUser,
ResponseUserId = friendRequest.ResponseUser
});
break;
//无效操作
default:
throw new BaseException(CodeDefine.INVALID_ACTION);
}
await _context.SaveChangesAsync();
return true;
}
#endregion
#region
public async Task<bool> SendFriendRequestAsync(FriendRequestDto dto)
{
//查询用户是否存在
bool isExist = await _context.Users.AnyAsync(x => x.Id == dto.ToUserId);
if (!isExist) throw new BaseException(CodeDefine.USER_NOT_FOUND);
bool isExistUser2 = await _context.Users.AnyAsync(x => x.Id == dto.FromUserId);
if(!isExistUser2) throw new BaseException(CodeDefine.USER_NOT_FOUND);
// 检查是否已有好友关系或待处理请求
bool alreadyExists = await _context.FriendRequests.AnyAsync(x =>
x.RequestUser == dto.FromUserId && x.ResponseUser == dto.ToUserId && x.State == (sbyte)FriendRequestState.Pending
);
if (alreadyExists)
throw new BaseException(CodeDefine.FRIEND_REQUEST_EXISTS);
var friendShip = await _context.Friends.FirstOrDefaultAsync(x => x.UserId == dto.FromUserId && x.FriendId == dto.ToUserId);
//检查是否被对方拉黑
bool isBlocked = friendShip != null && friendShip.StatusEnum == FriendStatus.Blocked;
if (isBlocked)
throw new BaseException(CodeDefine.FRIEND_REQUEST_REJECTED);
if (friendShip != null)
throw new BaseException(CodeDefine.ALREADY_FRIENDS);
//生成实体
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.UtcDateTime,
Description = friendRequst.Description,
EventId = Guid.NewGuid(),
FromUserId = friendRequst.RequestUser,
ToUserId = friendRequst.ResponseUser,
OperatorId = friendRequst.RequestUser
});
return true;
}
#endregion
#region
public async Task MakeFriendshipAsync(int userAId, int userBId, string? remarkName)
{
bool userAexist = await _context.Friends.AnyAsync(x => x.UserId == userAId && x.FriendId == userBId);
if (!userAexist)
{
User? userbInfo = await _context.Users.FirstOrDefaultAsync(x => x.Id == userBId);
if (userbInfo is null) throw new BaseException(CodeDefine.USER_NOT_FOUND);
Friend friendA = new Friend()
{
Avatar = userbInfo.Avatar,
Created = DateTime.Now,
FriendId = userbInfo.Id,
RemarkName = remarkName ?? userbInfo.NickName,
StatusEnum = FriendStatus.Added,
UserId = userAId
};
_context.Friends.Add(friendA);
await _context.SaveChangesAsync();
}
}
#endregion
}
}