feat: 完成会员消息触达后端模块
This commit is contained in:
@@ -0,0 +1,530 @@
|
||||
namespace TakeoutSaaS.Application.App.Members.MessageReach.Dto;
|
||||
|
||||
/// <summary>
|
||||
/// 消息触达统计 DTO。
|
||||
/// </summary>
|
||||
public sealed class MemberMessageReachStatsDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 本月发送消息条数。
|
||||
/// </summary>
|
||||
public int MonthlySentCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 本月触达人数。
|
||||
/// </summary>
|
||||
public int ReachMemberCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 打开率百分比(0-100)。
|
||||
/// </summary>
|
||||
public decimal OpenRate { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 转化率百分比(0-100)。
|
||||
/// </summary>
|
||||
public decimal ConversionRate { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 消息列表结果 DTO。
|
||||
/// </summary>
|
||||
public sealed class MemberMessageReachListResultDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 列表项。
|
||||
/// </summary>
|
||||
public IReadOnlyList<MemberMessageReachListItemDto> Items { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 总数。
|
||||
/// </summary>
|
||||
public int TotalCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 页码。
|
||||
/// </summary>
|
||||
public int Page { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 每页条数。
|
||||
/// </summary>
|
||||
public int PageSize { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 消息列表项 DTO。
|
||||
/// </summary>
|
||||
public sealed class MemberMessageReachListItemDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 消息标识。
|
||||
/// </summary>
|
||||
public long MessageId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 消息标题。
|
||||
/// </summary>
|
||||
public string Title { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 渠道。
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> Channels { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 目标描述。
|
||||
/// </summary>
|
||||
public string AudienceText { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 预计触达人数。
|
||||
/// </summary>
|
||||
public int EstimatedReachCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 发送状态。
|
||||
/// </summary>
|
||||
public string Status { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 发送时间(UTC)。
|
||||
/// </summary>
|
||||
public DateTime? SentAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 定时发送时间(UTC)。
|
||||
/// </summary>
|
||||
public DateTime? ScheduledAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 打开率百分比(0-100)。
|
||||
/// </summary>
|
||||
public decimal OpenRate { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 转化率百分比(0-100)。
|
||||
/// </summary>
|
||||
public decimal ConversionRate { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 消息详情 DTO。
|
||||
/// </summary>
|
||||
public sealed class MemberMessageReachDetailDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 消息标识。
|
||||
/// </summary>
|
||||
public long MessageId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 模板标识。
|
||||
/// </summary>
|
||||
public long? TemplateId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 消息标题。
|
||||
/// </summary>
|
||||
public string Title { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 消息正文。
|
||||
/// </summary>
|
||||
public string Content { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 渠道。
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> Channels { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 目标类型。
|
||||
/// </summary>
|
||||
public string AudienceType { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 目标标签。
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> AudienceTags { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 目标描述。
|
||||
/// </summary>
|
||||
public string AudienceText { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 预计触达人数。
|
||||
/// </summary>
|
||||
public int EstimatedReachCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 发送时间类型。
|
||||
/// </summary>
|
||||
public string ScheduleType { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 定时发送时间(UTC)。
|
||||
/// </summary>
|
||||
public DateTime? ScheduledAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 发送状态。
|
||||
/// </summary>
|
||||
public string Status { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 实际发送时间(UTC)。
|
||||
/// </summary>
|
||||
public DateTime? SentAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 发送成功数量。
|
||||
/// </summary>
|
||||
public int SentCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 已读数量。
|
||||
/// </summary>
|
||||
public int ReadCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 转化数量。
|
||||
/// </summary>
|
||||
public int ConvertedCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 打开率百分比(0-100)。
|
||||
/// </summary>
|
||||
public decimal OpenRate { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 转化率百分比(0-100)。
|
||||
/// </summary>
|
||||
public decimal ConversionRate { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后错误信息。
|
||||
/// </summary>
|
||||
public string? LastError { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 收件明细。
|
||||
/// </summary>
|
||||
public IReadOnlyList<MemberMessageReachRecipientDto> Recipients { get; init; } = [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收件明细 DTO。
|
||||
/// </summary>
|
||||
public sealed class MemberMessageReachRecipientDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 会员标识。
|
||||
/// </summary>
|
||||
public long MemberId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 渠道。
|
||||
/// </summary>
|
||||
public string Channel { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 状态。
|
||||
/// </summary>
|
||||
public string Status { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 手机号快照。
|
||||
/// </summary>
|
||||
public string? Mobile { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// OpenId 快照。
|
||||
/// </summary>
|
||||
public string? OpenId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 发送时间(UTC)。
|
||||
/// </summary>
|
||||
public DateTime? SentAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 已读时间(UTC)。
|
||||
/// </summary>
|
||||
public DateTime? ReadAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 转化时间(UTC)。
|
||||
/// </summary>
|
||||
public DateTime? ConvertedAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 失败信息。
|
||||
/// </summary>
|
||||
public string? ErrorMessage { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 模板列表结果 DTO。
|
||||
/// </summary>
|
||||
public sealed class MemberMessageTemplateListResultDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 列表项。
|
||||
/// </summary>
|
||||
public IReadOnlyList<MemberMessageTemplateDto> Items { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 总数。
|
||||
/// </summary>
|
||||
public int TotalCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 页码。
|
||||
/// </summary>
|
||||
public int Page { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 每页条数。
|
||||
/// </summary>
|
||||
public int PageSize { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 模板 DTO。
|
||||
/// </summary>
|
||||
public sealed class MemberMessageTemplateDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 模板标识。
|
||||
/// </summary>
|
||||
public long TemplateId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 模板名称。
|
||||
/// </summary>
|
||||
public string Name { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 模板分类。
|
||||
/// </summary>
|
||||
public string Category { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 模板内容。
|
||||
/// </summary>
|
||||
public string Content { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 使用次数。
|
||||
/// </summary>
|
||||
public int UsageCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 最近使用时间(UTC)。
|
||||
/// </summary>
|
||||
public DateTime? LastUsedAt { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 目标人群估算 DTO。
|
||||
/// </summary>
|
||||
public sealed class MemberMessageAudienceEstimateDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 预计触达人数。
|
||||
/// </summary>
|
||||
public int ReachCount { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 消息调度元信息 DTO。
|
||||
/// </summary>
|
||||
public sealed class MemberMessageDispatchMetaDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 消息标识。
|
||||
/// </summary>
|
||||
public long MessageId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 发送状态。
|
||||
/// </summary>
|
||||
public string Status { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 发送时间类型。
|
||||
/// </summary>
|
||||
public string ScheduleType { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 定时发送时间(UTC)。
|
||||
/// </summary>
|
||||
public DateTime? ScheduledAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Hangfire 任务 ID。
|
||||
/// </summary>
|
||||
public string? HangfireJobId { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存消息请求输入。
|
||||
/// </summary>
|
||||
public sealed class SaveMemberMessageInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 消息标识。
|
||||
/// </summary>
|
||||
public long? MessageId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 门店标识。
|
||||
/// </summary>
|
||||
public long? StoreId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 模板标识。
|
||||
/// </summary>
|
||||
public long? TemplateId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 标题。
|
||||
/// </summary>
|
||||
public string Title { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 内容。
|
||||
/// </summary>
|
||||
public string Content { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 渠道。
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> Channels { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 目标类型。
|
||||
/// </summary>
|
||||
public string AudienceType { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 目标标签。
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> AudienceTags { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 发送时间类型。
|
||||
/// </summary>
|
||||
public string ScheduleType { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 定时发送时间(UTC)。
|
||||
/// </summary>
|
||||
public DateTime? ScheduledAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 提交动作(draft/send)。
|
||||
/// </summary>
|
||||
public string SubmitAction { get; init; } = "draft";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 搜索消息输入。
|
||||
/// </summary>
|
||||
public sealed class SearchMemberMessageInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 状态过滤。
|
||||
/// </summary>
|
||||
public string? Status { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 渠道过滤。
|
||||
/// </summary>
|
||||
public string? Channel { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 标题关键词。
|
||||
/// </summary>
|
||||
public string? Keyword { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 页码。
|
||||
/// </summary>
|
||||
public int Page { get; init; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 每页条数。
|
||||
/// </summary>
|
||||
public int PageSize { get; init; } = 10;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 搜索模板输入。
|
||||
/// </summary>
|
||||
public sealed class SearchMemberMessageTemplateInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 分类。
|
||||
/// </summary>
|
||||
public string? Category { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 关键词。
|
||||
/// </summary>
|
||||
public string? Keyword { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 页码。
|
||||
/// </summary>
|
||||
public int Page { get; init; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 每页条数。
|
||||
/// </summary>
|
||||
public int PageSize { get; init; } = 10;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存模板输入。
|
||||
/// </summary>
|
||||
public sealed class SaveMemberMessageTemplateInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 模板标识。
|
||||
/// </summary>
|
||||
public long? TemplateId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 模板名称。
|
||||
/// </summary>
|
||||
public string Name { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 模板分类。
|
||||
/// </summary>
|
||||
public string Category { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 模板内容。
|
||||
/// </summary>
|
||||
public string Content { get; init; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 估算人群输入。
|
||||
/// </summary>
|
||||
public sealed class MemberMessageAudienceEstimateInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 目标类型。
|
||||
/// </summary>
|
||||
public string AudienceType { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 标签列表。
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> Tags { get; init; } = [];
|
||||
}
|
||||
Reference in New Issue
Block a user