Files
emall-api/FutureMailAPI/Services/MailService.cs
2025-10-16 09:56:36 +08:00

475 lines
18 KiB
C#

using Microsoft.EntityFrameworkCore;
using FutureMailAPI.Data;
using FutureMailAPI.Models;
using FutureMailAPI.DTOs;
namespace FutureMailAPI.Services
{
public class MailService : IMailService
{
private readonly FutureMailDbContext _context;
public MailService(FutureMailDbContext context)
{
_context = context;
}
public async Task<ApiResponse<SentMailResponseDto>> CreateMailAsync(int userId, SentMailCreateDto createDto)
{
// 检查投递时间是否在未来
if (createDto.DeliveryTime <= DateTime.UtcNow)
{
return ApiResponse<SentMailResponseDto>.ErrorResult("投递时间必须是未来时间");
}
// 如果是指定用户,检查用户是否存在
int? recipientId = null;
if (createDto.RecipientType == 1 && !string.IsNullOrEmpty(createDto.RecipientEmail))
{
var recipient = await _context.Users
.FirstOrDefaultAsync(u => u.Email == createDto.RecipientEmail);
if (recipient == null)
{
return ApiResponse<SentMailResponseDto>.ErrorResult("收件人不存在");
}
recipientId = recipient.Id;
}
// 创建邮件
var mail = new SentMail
{
Title = createDto.Title,
Content = createDto.Content,
SenderId = userId,
RecipientType = createDto.RecipientType,
RecipientId = recipientId,
DeliveryTime = createDto.DeliveryTime,
SentAt = DateTime.UtcNow, // 显式设置发送时间
Status = createDto.DeliveryTime > DateTime.UtcNow ? 1 : 0, // 根据投递时间直接设置状态
TriggerType = createDto.TriggerType,
TriggerDetails = createDto.TriggerDetails,
Attachments = createDto.Attachments,
IsEncrypted = createDto.IsEncrypted,
EncryptionKey = createDto.EncryptionKey,
Theme = createDto.Theme
};
_context.SentMails.Add(mail);
await _context.SaveChangesAsync();
// 如果是发送状态(不是草稿),创建时间胶囊
if (mail.Status == 1) // 已发送(待投递)
{
// 创建时间胶囊
var timeCapsule = new TimeCapsule
{
UserId = userId,
SentMailId = mail.Id,
PositionX = 0,
PositionY = 0,
PositionZ = 0,
Status = 1, // 漂浮中
Type = 0 // 普通
};
_context.TimeCapsules.Add(timeCapsule);
await _context.SaveChangesAsync();
}
var mailResponse = await GetSentMailWithDetailsAsync(mail.Id);
return ApiResponse<SentMailResponseDto>.SuccessResult(mailResponse, "邮件创建成功");
}
public async Task<ApiResponse<PagedResponse<SentMailResponseDto>>> GetSentMailsAsync(int userId, MailListQueryDto queryDto)
{
var query = _context.SentMails
.Where(m => m.SenderId == userId)
.Include(m => m.Sender)
.Include(m => m.Recipient)
.AsQueryable();
// 应用筛选条件
if (queryDto.Status.HasValue)
{
query = query.Where(m => m.Status == queryDto.Status.Value);
}
if (queryDto.RecipientType.HasValue)
{
query = query.Where(m => m.RecipientType == queryDto.RecipientType.Value);
}
if (!string.IsNullOrEmpty(queryDto.Keyword))
{
query = query.Where(m => m.Title.Contains(queryDto.Keyword) || m.Content.Contains(queryDto.Keyword));
}
if (queryDto.StartDate.HasValue)
{
query = query.Where(m => m.SentAt >= queryDto.StartDate.Value);
}
if (queryDto.EndDate.HasValue)
{
query = query.Where(m => m.SentAt <= queryDto.EndDate.Value);
}
// 排序
query = query.OrderByDescending(m => m.SentAt);
// 分页
var totalCount = await query.CountAsync();
var mails = await query
.Skip((queryDto.PageIndex - 1) * queryDto.PageSize)
.Take(queryDto.PageSize)
.ToListAsync();
var mailDtos = mails.Select(MapToSentMailResponseDto).ToList();
var pagedResponse = new PagedResponse<SentMailResponseDto>(
mailDtos, queryDto.PageIndex, queryDto.PageSize, totalCount);
return ApiResponse<PagedResponse<SentMailResponseDto>>.SuccessResult(pagedResponse);
}
public async Task<ApiResponse<SentMailResponseDto>> GetSentMailByIdAsync(int userId, int mailId)
{
var mail = await _context.SentMails
.Include(m => m.Sender)
.Include(m => m.Recipient)
.FirstOrDefaultAsync(m => m.Id == mailId && m.SenderId == userId);
if (mail == null)
{
return ApiResponse<SentMailResponseDto>.ErrorResult("邮件不存在");
}
var mailDto = MapToSentMailResponseDto(mail);
return ApiResponse<SentMailResponseDto>.SuccessResult(mailDto);
}
public async Task<ApiResponse<SentMailResponseDto>> UpdateMailAsync(int userId, int mailId, SentMailUpdateDto updateDto)
{
var mail = await _context.SentMails
.FirstOrDefaultAsync(m => m.Id == mailId && m.SenderId == userId);
if (mail == null)
{
return ApiResponse<SentMailResponseDto>.ErrorResult("邮件不存在");
}
// 检查邮件是否已投递,已投递的邮件不能修改
if (mail.Status >= 2)
{
return ApiResponse<SentMailResponseDto>.ErrorResult("已投递的邮件不能修改");
}
// 更新邮件信息
if (updateDto.Title != null)
{
mail.Title = updateDto.Title;
}
if (updateDto.Content != null)
{
mail.Content = updateDto.Content;
}
if (updateDto.DeliveryTime.HasValue)
{
if (updateDto.DeliveryTime.Value <= DateTime.UtcNow)
{
return ApiResponse<SentMailResponseDto>.ErrorResult("投递时间必须是未来时间");
}
mail.DeliveryTime = updateDto.DeliveryTime.Value;
}
if (updateDto.TriggerDetails != null)
{
mail.TriggerDetails = updateDto.TriggerDetails;
}
if (updateDto.Attachments != null)
{
mail.Attachments = updateDto.Attachments;
}
if (updateDto.Theme != null)
{
mail.Theme = updateDto.Theme;
}
await _context.SaveChangesAsync();
var mailResponse = await GetSentMailWithDetailsAsync(mail.Id);
return ApiResponse<SentMailResponseDto>.SuccessResult(mailResponse, "邮件更新成功");
}
public async Task<ApiResponse<bool>> DeleteMailAsync(int userId, int mailId)
{
var mail = await _context.SentMails
.FirstOrDefaultAsync(m => m.Id == mailId && m.SenderId == userId);
if (mail == null)
{
return ApiResponse<bool>.ErrorResult("邮件不存在");
}
// 检查邮件是否已投递,已投递的邮件不能删除
if (mail.Status >= 2)
{
return ApiResponse<bool>.ErrorResult("已投递的邮件不能删除");
}
// 删除相关的时间胶囊
var timeCapsule = await _context.TimeCapsules
.FirstOrDefaultAsync(tc => tc.SentMailId == mailId);
if (timeCapsule != null)
{
_context.TimeCapsules.Remove(timeCapsule);
}
// 删除邮件
_context.SentMails.Remove(mail);
await _context.SaveChangesAsync();
return ApiResponse<bool>.SuccessResult(true, "邮件删除成功");
}
public async Task<ApiResponse<PagedResponse<ReceivedMailResponseDto>>> GetReceivedMailsAsync(int userId, MailListQueryDto queryDto)
{
var query = _context.ReceivedMails
.Where(r => r.RecipientId == userId)
.Include(r => r.SentMail)
.ThenInclude(m => m.Sender)
.AsQueryable();
// 应用筛选条件
if (queryDto.Status.HasValue)
{
if (queryDto.Status.Value == 0) // 未读
{
query = query.Where(r => !r.IsRead);
}
else if (queryDto.Status.Value == 1) // 已读
{
query = query.Where(r => r.IsRead);
}
}
if (!string.IsNullOrEmpty(queryDto.Keyword))
{
query = query.Where(r => r.SentMail.Title.Contains(queryDto.Keyword) || r.SentMail.Content.Contains(queryDto.Keyword));
}
if (queryDto.StartDate.HasValue)
{
query = query.Where(r => r.ReceivedAt >= queryDto.StartDate.Value);
}
if (queryDto.EndDate.HasValue)
{
query = query.Where(r => r.ReceivedAt <= queryDto.EndDate.Value);
}
// 排序
query = query.OrderByDescending(r => r.ReceivedAt);
// 分页
var totalCount = await query.CountAsync();
var receivedMails = await query
.Skip((queryDto.PageIndex - 1) * queryDto.PageSize)
.Take(queryDto.PageSize)
.ToListAsync();
var mailDtos = receivedMails.Select(MapToReceivedMailResponseDto).ToList();
var pagedResponse = new PagedResponse<ReceivedMailResponseDto>(
mailDtos, queryDto.PageIndex, queryDto.PageSize, totalCount);
return ApiResponse<PagedResponse<ReceivedMailResponseDto>>.SuccessResult(pagedResponse);
}
public async Task<ApiResponse<ReceivedMailResponseDto>> GetReceivedMailByIdAsync(int userId, int mailId)
{
var receivedMail = await _context.ReceivedMails
.Include(r => r.SentMail)
.ThenInclude(m => m.Sender)
.FirstOrDefaultAsync(r => r.Id == mailId && r.RecipientId == userId);
if (receivedMail == null)
{
return ApiResponse<ReceivedMailResponseDto>.ErrorResult("邮件不存在");
}
var mailDto = MapToReceivedMailResponseDto(receivedMail);
return ApiResponse<ReceivedMailResponseDto>.SuccessResult(mailDto);
}
public async Task<ApiResponse<bool>> MarkReceivedMailAsReadAsync(int userId, int mailId)
{
var receivedMail = await _context.ReceivedMails
.FirstOrDefaultAsync(r => r.Id == mailId && r.RecipientId == userId);
if (receivedMail == null)
{
return ApiResponse<bool>.ErrorResult("邮件不存在");
}
if (!receivedMail.IsRead)
{
receivedMail.IsRead = true;
receivedMail.ReadAt = DateTime.UtcNow;
await _context.SaveChangesAsync();
}
return ApiResponse<bool>.SuccessResult(true, "邮件已标记为已读");
}
public Task<ApiResponse<SentMailResponseDto>> GetMailByIdAsync(int userId, int mailId)
{
return GetSentMailByIdAsync(userId, mailId);
}
public Task<ApiResponse<PagedResponse<SentMailResponseDto>>> GetMailsAsync(int userId, MailListQueryDto queryDto)
{
return GetSentMailsAsync(userId, queryDto);
}
public Task<ApiResponse<bool>> MarkAsReadAsync(int userId, int mailId)
{
return MarkReceivedMailAsReadAsync(userId, mailId);
}
public async Task<ApiResponse<bool>> RevokeMailAsync(int userId, int mailId)
{
var mail = await _context.SentMails
.FirstOrDefaultAsync(m => m.Id == mailId && m.SenderId == userId);
if (mail == null)
{
return ApiResponse<bool>.ErrorResult("邮件不存在");
}
// 检查邮件是否已投递,已投递的邮件不能撤销
if (mail.Status >= 2)
{
return ApiResponse<bool>.ErrorResult("已投递的邮件不能撤销");
}
// 更新邮件状态为已撤销
mail.Status = 4; // 4-已撤销
await _context.SaveChangesAsync();
// 更新相关的时间胶囊状态
var timeCapsule = await _context.TimeCapsules
.FirstOrDefaultAsync(tc => tc.SentMailId == mailId);
if (timeCapsule != null)
{
timeCapsule.Status = 3; // 3-已撤销
await _context.SaveChangesAsync();
}
return ApiResponse<bool>.SuccessResult(true, "邮件已撤销");
}
private async Task<SentMailResponseDto> GetSentMailWithDetailsAsync(int mailId)
{
var mail = await _context.SentMails
.Include(m => m.Sender)
.Include(m => m.Recipient)
.FirstOrDefaultAsync(m => m.Id == mailId);
return MapToSentMailResponseDto(mail!);
}
private static SentMailResponseDto MapToSentMailResponseDto(SentMail mail)
{
return new SentMailResponseDto
{
Id = mail.Id,
Title = mail.Title,
Content = mail.Content,
SenderId = mail.SenderId,
SenderUsername = mail.Sender?.Username ?? "",
RecipientType = mail.RecipientType,
RecipientId = mail.RecipientId,
RecipientUsername = mail.Recipient?.Username ?? "",
SentAt = mail.SentAt,
DeliveryTime = mail.DeliveryTime,
Status = mail.Status,
StatusText = GetStatusText(mail.Status),
TriggerType = mail.TriggerType,
TriggerTypeText = GetTriggerTypeText(mail.TriggerType),
TriggerDetails = mail.TriggerDetails,
Attachments = mail.Attachments,
IsEncrypted = mail.IsEncrypted,
Theme = mail.Theme,
RecipientTypeText = GetRecipientTypeText(mail.RecipientType),
DaysUntilDelivery = (int)(mail.DeliveryTime - DateTime.UtcNow).TotalDays
};
}
private static ReceivedMailResponseDto MapToReceivedMailResponseDto(ReceivedMail receivedMail)
{
return new ReceivedMailResponseDto
{
Id = receivedMail.Id,
SentMailId = receivedMail.SentMailId,
Title = receivedMail.SentMail.Title,
Content = receivedMail.SentMail.Content,
SenderUsername = receivedMail.SentMail.Sender?.Username ?? "",
SentAt = receivedMail.SentMail.SentAt,
ReceivedAt = receivedMail.ReceivedAt,
IsRead = receivedMail.IsRead,
ReadAt = receivedMail.ReadAt,
IsReplied = receivedMail.IsReplied,
ReplyMailId = receivedMail.ReplyMailId,
Theme = receivedMail.SentMail.Theme
};
}
private static string GetStatusText(int status)
{
return status switch
{
0 => "草稿",
1 => "已发送(待投递)",
2 => "投递中",
3 => "已送达",
_ => "未知"
};
}
private static string GetRecipientTypeText(int recipientType)
{
return recipientType switch
{
0 => "自己",
1 => "指定用户",
2 => "公开时间胶囊",
_ => "未知"
};
}
private static string GetTriggerTypeText(int triggerType)
{
return triggerType switch
{
0 => "时间",
1 => "地点",
2 => "事件",
_ => "未知"
};
}
}
}