live-forum/server/webapi/LiveForum/LiveForum.Service/Messages/MessageEventHandler.cs
2026-03-24 11:27:37 +08:00

335 lines
12 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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) + "...";
}
}
}