335 lines
12 KiB
C#
335 lines
12 KiB
C#
using FreeSql;
|
||
using LiveForum.Code.Base;
|
||
using LiveForum.IService.Messages;
|
||
using LiveForum.IService.Others;
|
||
using LiveForum.IService.Users;
|
||
using LiveForum.Model;
|
||
using LiveForum.Model.Dto.Users;
|
||
using LiveForum.Model.Events;
|
||
using Microsoft.Extensions.Logging;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text.Json;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace LiveForum.Service.Messages
|
||
{
|
||
/// <summary>
|
||
/// 消息事件处理器实现
|
||
/// 将事件转换为数据库消息记录(重量级,包含用户信息查询和快照构造)
|
||
/// </summary>
|
||
public class MessageEventHandler : IMessageEventHandler
|
||
{
|
||
private readonly IBaseRepository<T_Messages> _messagesRepository;
|
||
private readonly IBaseRepository<T_Users> _usersRepository;
|
||
private readonly IBaseRepository<T_Posts> _postsRepository;
|
||
private readonly IBaseRepository<T_Comments> _commentsRepository;
|
||
private readonly IUserInfoService _userInfoService;
|
||
private readonly ILogger<MessageEventHandler> _logger;
|
||
|
||
public MessageEventHandler(
|
||
IBaseRepository<T_Messages> messagesRepository,
|
||
IBaseRepository<T_Users> usersRepository,
|
||
IBaseRepository<T_Posts> postsRepository,
|
||
IBaseRepository<T_Comments> commentsRepository,
|
||
IUserInfoService userInfoService,
|
||
ILogger<MessageEventHandler> logger)
|
||
{
|
||
_messagesRepository = messagesRepository;
|
||
_usersRepository = usersRepository;
|
||
_postsRepository = postsRepository;
|
||
_commentsRepository = commentsRepository;
|
||
_userInfoService = userInfoService;
|
||
_logger = logger;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理点赞事件
|
||
/// </summary>
|
||
public async Task HandleLikeEventAsync(LikeEvent evt)
|
||
{
|
||
try
|
||
{
|
||
// 幂等性检查
|
||
if (await IsEventProcessedAsync(evt.EventId))
|
||
{
|
||
_logger.LogWarning("[EventHandler] 事件已处理过,跳过: {EventId}", evt.EventId);
|
||
return;
|
||
}
|
||
|
||
// 查询触发者用户信息
|
||
var sender = await _usersRepository.Select
|
||
.Where(x => x.Id == evt.TriggerId)
|
||
.FirstAsync();
|
||
|
||
if (sender == null)
|
||
{
|
||
_logger.LogWarning("[EventHandler] 用户不存在,跳过点赞消息创建: TriggerId={TriggerId}", evt.TriggerId);
|
||
return;
|
||
}
|
||
|
||
// 使用服务转换为 UserInfoDto(自动获取认证类型数据)
|
||
var senderInfo = await _userInfoService.ToUserInfoDtoAsync(sender);
|
||
|
||
// 组装消息标题和内容
|
||
string messageTitle;
|
||
string messageContent;
|
||
|
||
if (evt.ContentType == 1)
|
||
{
|
||
messageTitle = $"点赞了我的帖子";
|
||
messageContent = $"帖子标题:{evt.Content?.PostTitle ?? ""}";
|
||
}
|
||
else if (evt.ContentType == 2)
|
||
{
|
||
messageTitle = $"点赞了我的评论";
|
||
messageContent = $"评论内容:{TruncateText(evt.Content?.CommentContent, 50)}";
|
||
}
|
||
else if (evt.ContentType == 3) // 送花
|
||
{
|
||
messageTitle = $"给我送花";
|
||
messageContent = evt.Content?.PostTitle ?? ""; // "送了 X 朵花"
|
||
}
|
||
else
|
||
{
|
||
messageTitle = $"点赞了我";
|
||
messageContent = "";
|
||
}
|
||
|
||
// 序列化用户信息
|
||
var senderInfoJson = JsonSerializer.Serialize(senderInfo, new JsonSerializerOptions
|
||
{
|
||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||
});
|
||
|
||
var contentSnapshotJson = JsonSerializer.Serialize(evt.Content, new JsonSerializerOptions
|
||
{
|
||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||
});
|
||
|
||
// 创建消息记录
|
||
var message = new T_Messages
|
||
{
|
||
ReceiverId = evt.ReceiverId,
|
||
SenderId = evt.TriggerId,
|
||
MessageType = 2, // 点赞消息
|
||
MessageTitle = messageTitle,
|
||
MessageContent = messageContent,
|
||
ContentType = evt.ContentType,
|
||
ContentId = evt.ContentId,
|
||
IsRead = false,
|
||
SenderInfo = senderInfoJson,
|
||
EventId = evt.EventId,
|
||
ContentSnapshot = contentSnapshotJson,
|
||
CreatedAt = evt.OccurredAt
|
||
};
|
||
|
||
await _messagesRepository.InsertAsync(message);
|
||
|
||
_logger.LogInformation(
|
||
"[EventHandler] 点赞消息已创建: EventId={EventId}, ContentType={ContentType}, ContentId={ContentId}",
|
||
evt.EventId, evt.ContentType, evt.ContentId);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex,
|
||
"[EventHandler] 处理点赞事件失败: EventId={EventId}",
|
||
evt.EventId);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理评论回复事件
|
||
/// </summary>
|
||
public async Task HandleCommentReplyEventAsync(CommentReplyEvent evt)
|
||
{
|
||
try
|
||
{
|
||
// 幂等性检查
|
||
if (await IsEventProcessedAsync(evt.EventId))
|
||
{
|
||
_logger.LogWarning("[EventHandler] 事件已处理过,跳过: {EventId}", evt.EventId);
|
||
return;
|
||
}
|
||
|
||
// 查询触发者用户信息
|
||
var sender = await _usersRepository.Select
|
||
.Where(x => x.Id == evt.TriggerId)
|
||
.FirstAsync();
|
||
|
||
if (sender == null)
|
||
{
|
||
_logger.LogWarning("[EventHandler] 用户不存在,跳过回复消息创建: TriggerId={TriggerId}", evt.TriggerId);
|
||
return;
|
||
}
|
||
|
||
// 使用服务转换为 UserInfoDto(自动获取认证类型数据)
|
||
var senderInfo = await _userInfoService.ToUserInfoDtoAsync(sender);
|
||
|
||
// 组装消息标题
|
||
string messageTitle;
|
||
if (evt.IsDirectComment)
|
||
{
|
||
messageTitle = $"评论了你的帖子";
|
||
}
|
||
else
|
||
{
|
||
messageTitle = $"回复了我的评论";
|
||
}
|
||
|
||
string messageContent = $"回复内容:{TruncateText(evt.CommentContent, 50)}";
|
||
|
||
// 序列化用户信息
|
||
var senderInfoJson = JsonSerializer.Serialize(senderInfo, new JsonSerializerOptions
|
||
{
|
||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||
});
|
||
|
||
// 组装内容快照
|
||
var contentSnapshot = new ContentSnapshot
|
||
{
|
||
PostId = evt.PostId,
|
||
PostTitle = evt.PostTitle,
|
||
CommentId = evt.CommentId,
|
||
CommentContent = evt.CommentContent
|
||
};
|
||
|
||
var contentSnapshotJson = JsonSerializer.Serialize(contentSnapshot, new JsonSerializerOptions
|
||
{
|
||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||
});
|
||
|
||
// 创建消息记录
|
||
var message = new T_Messages
|
||
{
|
||
ReceiverId = evt.ReceiverId,
|
||
SenderId = evt.TriggerId,
|
||
MessageType = 1, // 回复消息
|
||
MessageTitle = messageTitle,
|
||
MessageContent = messageContent,
|
||
MyCommentContent = evt.MyCommentContent, // 保存我的评论内容
|
||
ContentType = 2, // 评论类型
|
||
ContentId = evt.CommentId,
|
||
IsRead = false,
|
||
SenderInfo = senderInfoJson,
|
||
EventId = evt.EventId,
|
||
ContentSnapshot = contentSnapshotJson,
|
||
CreatedAt = evt.OccurredAt
|
||
};
|
||
|
||
await _messagesRepository.InsertAsync(message);
|
||
|
||
_logger.LogInformation(
|
||
"[EventHandler] 评论回复消息已创建: EventId={EventId}, CommentId={CommentId}, IsDirectComment={IsDirectComment}",
|
||
evt.EventId, evt.CommentId, evt.IsDirectComment);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex,
|
||
"[EventHandler] 处理评论回复事件失败: EventId={EventId}",
|
||
evt.EventId);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理自定义消息事件
|
||
/// </summary>
|
||
public async Task HandleCustomMessageEventAsync(CustomMessageEvent evt)
|
||
{
|
||
try
|
||
{
|
||
// 幂等性检查
|
||
if (await IsEventProcessedAsync(evt.EventId))
|
||
{
|
||
_logger.LogWarning("[EventHandler] 事件已处理过,跳过: {EventId}", evt.EventId);
|
||
return;
|
||
}
|
||
|
||
// 查询触发者用户信息
|
||
var sender = await _usersRepository.Select
|
||
.Where(x => x.Id == evt.TriggerId)
|
||
.FirstAsync();
|
||
|
||
if (sender == null)
|
||
{
|
||
_logger.LogWarning("[EventHandler] 用户不存在,跳过自定义消息创建: TriggerId={TriggerId}", evt.TriggerId);
|
||
return;
|
||
}
|
||
|
||
// 使用服务转换为 UserInfoDto(自动获取认证类型数据)
|
||
var senderInfo = await _userInfoService.ToUserInfoDtoAsync(sender);
|
||
|
||
// 序列化用户信息
|
||
var senderInfoJson = JsonSerializer.Serialize(senderInfo, new JsonSerializerOptions
|
||
{
|
||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||
});
|
||
|
||
// 创建消息记录
|
||
var message = new T_Messages
|
||
{
|
||
ReceiverId = evt.ReceiverId,
|
||
SenderId = evt.TriggerId,
|
||
MessageType = evt.MessageType, // 1-回复,2-点赞
|
||
MessageTitle = evt.Title,
|
||
MessageContent = evt.Content,
|
||
MyCommentContent = evt.MyCommentContent,
|
||
ContentType = 0, // 自定义消息没有具体内容类型
|
||
ContentId = null,
|
||
IsRead = false,
|
||
SenderInfo = senderInfoJson,
|
||
EventId = evt.EventId,
|
||
ContentSnapshot = null,
|
||
CreatedAt = evt.OccurredAt
|
||
};
|
||
|
||
await _messagesRepository.InsertAsync(message);
|
||
|
||
_logger.LogInformation(
|
||
"[EventHandler] 自定义消息已创建: EventId={EventId}, MessageType={MessageType}",
|
||
evt.EventId, evt.MessageType);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex,
|
||
"[EventHandler] 处理自定义消息事件失败: EventId={EventId}",
|
||
evt.EventId);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查事件是否已经处理过(幂等性检查)
|
||
/// </summary>
|
||
private async Task<bool> IsEventProcessedAsync(string eventId)
|
||
{
|
||
if (string.IsNullOrEmpty(eventId))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
var exists = await _messagesRepository.Select
|
||
.Where(x => x.EventId == eventId)
|
||
.AnyAsync();
|
||
|
||
return exists;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 截断文本
|
||
/// </summary>
|
||
private string TruncateText(string text, int maxLength)
|
||
{
|
||
if (string.IsNullOrEmpty(text) || text.Length <= maxLength)
|
||
{
|
||
return text ?? "";
|
||
}
|
||
|
||
return text.Substring(0, maxLength) + "...";
|
||
}
|
||
}
|
||
}
|