531 lines
12 KiB
C#
531 lines
12 KiB
C#
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; } = [];
|
||
}
|