Files
emall-api/FutureMailAPI/Services/TimeCapsuleService.cs

436 lines
17 KiB
C#
Raw Normal View History

2025-10-16 09:56:36 +08:00
using Microsoft.EntityFrameworkCore;
using FutureMailAPI.Data;
using FutureMailAPI.Models;
using FutureMailAPI.DTOs;
namespace FutureMailAPI.Services
{
public class TimeCapsuleService : ITimeCapsuleService
{
private readonly FutureMailDbContext _context;
public TimeCapsuleService(FutureMailDbContext context)
{
_context = context;
}
public async Task<ApiResponse<TimeCapsuleResponseDto>> CreateTimeCapsuleAsync(int userId, TimeCapsuleCreateDto createDto)
{
// 检查邮件是否存在且属于当前用户
var mail = await _context.SentMails
.FirstOrDefaultAsync(m => m.Id == createDto.SentMailId && m.SenderId == userId);
if (mail == null)
{
return ApiResponse<TimeCapsuleResponseDto>.ErrorResult("邮件不存在或无权限");
}
// 检查是否已存在时间胶囊
var existingCapsule = await _context.TimeCapsules
.FirstOrDefaultAsync(tc => tc.SentMailId == createDto.SentMailId);
if (existingCapsule != null)
{
return ApiResponse<TimeCapsuleResponseDto>.ErrorResult("该邮件已创建时间胶囊");
}
// 创建时间胶囊
var timeCapsule = new TimeCapsule
{
UserId = userId,
SentMailId = createDto.SentMailId,
PositionX = createDto.PositionX,
PositionY = createDto.PositionY,
PositionZ = createDto.PositionZ,
Size = createDto.Size,
Color = createDto.Color,
Opacity = createDto.Opacity,
Rotation = createDto.Rotation,
Status = 1, // 漂浮中
Type = createDto.Type
};
_context.TimeCapsules.Add(timeCapsule);
await _context.SaveChangesAsync();
var capsuleResponse = await GetTimeCapsuleWithDetailsAsync(timeCapsule.Id);
return ApiResponse<TimeCapsuleResponseDto>.SuccessResult(capsuleResponse, "时间胶囊创建成功");
}
public async Task<ApiResponse<PagedResponse<TimeCapsuleResponseDto>>> GetTimeCapsulesAsync(int userId, TimeCapsuleListQueryDto queryDto)
{
var query = _context.TimeCapsules
.Where(tc => tc.UserId == userId)
.Include(tc => tc.User)
.Include(tc => tc.SentMail)
.AsQueryable();
// 应用筛选条件
if (queryDto.Status.HasValue)
{
query = query.Where(tc => tc.Status == queryDto.Status.Value);
}
if (queryDto.Type.HasValue)
{
query = query.Where(tc => tc.Type == queryDto.Type.Value);
}
if (queryDto.IncludeExpired.HasValue && !queryDto.IncludeExpired.Value)
{
query = query.Where(tc => tc.SentMail.DeliveryTime > DateTime.UtcNow);
}
// 排序
query = query.OrderByDescending(tc => tc.CreatedAt);
// 分页
var totalCount = await query.CountAsync();
var capsules = await query
.Skip((queryDto.PageIndex - 1) * queryDto.PageSize)
.Take(queryDto.PageSize)
.ToListAsync();
var capsuleDtos = capsules.Select(MapToTimeCapsuleResponseDto).ToList();
var pagedResponse = new PagedResponse<TimeCapsuleResponseDto>(
capsuleDtos, queryDto.PageIndex, queryDto.PageSize, totalCount);
return ApiResponse<PagedResponse<TimeCapsuleResponseDto>>.SuccessResult(pagedResponse);
}
public async Task<ApiResponse<TimeCapsuleResponseDto>> GetTimeCapsuleByIdAsync(int userId, int capsuleId)
{
var timeCapsule = await _context.TimeCapsules
.Include(tc => tc.User)
.Include(tc => tc.SentMail)
.FirstOrDefaultAsync(tc => tc.Id == capsuleId && tc.UserId == userId);
if (timeCapsule == null)
{
return ApiResponse<TimeCapsuleResponseDto>.ErrorResult("时间胶囊不存在");
}
var capsuleDto = MapToTimeCapsuleResponseDto(timeCapsule);
return ApiResponse<TimeCapsuleResponseDto>.SuccessResult(capsuleDto);
}
public async Task<ApiResponse<TimeCapsuleResponseDto>> UpdateTimeCapsuleAsync(int userId, int capsuleId, TimeCapsuleUpdateDto updateDto)
{
var timeCapsule = await _context.TimeCapsules
.FirstOrDefaultAsync(tc => tc.Id == capsuleId && tc.UserId == userId);
if (timeCapsule == null)
{
return ApiResponse<TimeCapsuleResponseDto>.ErrorResult("时间胶囊不存在");
}
// 检查胶囊是否已开启,已开启的胶囊不能修改
if (timeCapsule.Status >= 3)
{
return ApiResponse<TimeCapsuleResponseDto>.ErrorResult("已开启的时间胶囊不能修改");
}
// 更新胶囊信息
if (updateDto.PositionX.HasValue)
{
timeCapsule.PositionX = updateDto.PositionX.Value;
}
if (updateDto.PositionY.HasValue)
{
timeCapsule.PositionY = updateDto.PositionY.Value;
}
if (updateDto.PositionZ.HasValue)
{
timeCapsule.PositionZ = updateDto.PositionZ.Value;
}
if (updateDto.Size.HasValue)
{
timeCapsule.Size = updateDto.Size.Value;
}
if (updateDto.Color != null)
{
timeCapsule.Color = updateDto.Color;
}
if (updateDto.Opacity.HasValue)
{
timeCapsule.Opacity = updateDto.Opacity.Value;
}
if (updateDto.Rotation.HasValue)
{
timeCapsule.Rotation = updateDto.Rotation.Value;
}
await _context.SaveChangesAsync();
var capsuleResponse = await GetTimeCapsuleWithDetailsAsync(timeCapsule.Id);
return ApiResponse<TimeCapsuleResponseDto>.SuccessResult(capsuleResponse, "时间胶囊更新成功");
}
public async Task<ApiResponse<bool>> DeleteTimeCapsuleAsync(int userId, int capsuleId)
{
var timeCapsule = await _context.TimeCapsules
.FirstOrDefaultAsync(tc => tc.Id == capsuleId && tc.UserId == userId);
if (timeCapsule == null)
{
return ApiResponse<bool>.ErrorResult("时间胶囊不存在");
}
// 检查胶囊是否已开启,已开启的胶囊不能删除
if (timeCapsule.Status >= 3)
{
return ApiResponse<bool>.ErrorResult("已开启的时间胶囊不能删除");
}
// 删除时间胶囊
_context.TimeCapsules.Remove(timeCapsule);
await _context.SaveChangesAsync();
return ApiResponse<bool>.SuccessResult(true, "时间胶囊删除成功");
}
public async Task<ApiResponse<PagedResponse<TimeCapsuleResponseDto>>> GetPublicTimeCapsulesAsync(TimeCapsuleListQueryDto queryDto)
{
var query = _context.TimeCapsules
.Where(tc => tc.SentMail.RecipientType == 2) // 公开时间胶囊
.Include(tc => tc.User)
.Include(tc => tc.SentMail)
.AsQueryable();
// 应用筛选条件
if (queryDto.Status.HasValue)
{
query = query.Where(tc => tc.Status == queryDto.Status.Value);
}
if (queryDto.Type.HasValue)
{
query = query.Where(tc => tc.Type == queryDto.Type.Value);
}
if (queryDto.IncludeExpired.HasValue && !queryDto.IncludeExpired.Value)
{
query = query.Where(tc => tc.SentMail.DeliveryTime > DateTime.UtcNow);
}
// 排序
query = query.OrderByDescending(tc => tc.CreatedAt);
// 分页
var totalCount = await query.CountAsync();
var capsules = await query
.Skip((queryDto.PageIndex - 1) * queryDto.PageSize)
.Take(queryDto.PageSize)
.ToListAsync();
var capsuleDtos = capsules.Select(MapToTimeCapsuleResponseDto).ToList();
var pagedResponse = new PagedResponse<TimeCapsuleResponseDto>(
capsuleDtos, queryDto.PageIndex, queryDto.PageSize, totalCount);
return ApiResponse<PagedResponse<TimeCapsuleResponseDto>>.SuccessResult(pagedResponse);
}
public async Task<ApiResponse<TimeCapsuleResponseDto>> ClaimPublicCapsuleAsync(int userId, int capsuleId)
{
var timeCapsule = await _context.TimeCapsules
.Include(tc => tc.SentMail)
.FirstOrDefaultAsync(tc => tc.Id == capsuleId && tc.SentMail.RecipientType == 2);
if (timeCapsule == null)
{
return ApiResponse<TimeCapsuleResponseDto>.ErrorResult("时间胶囊不存在或不是公开胶囊");
}
// 检查胶囊是否已开启
if (timeCapsule.Status >= 3)
{
return ApiResponse<TimeCapsuleResponseDto>.ErrorResult("时间胶囊已开启");
}
// 检查是否已认领
var existingReceivedMail = await _context.ReceivedMails
.FirstOrDefaultAsync(rm => rm.SentMailId == timeCapsule.SentMailId && rm.RecipientId == userId);
if (existingReceivedMail != null)
{
return ApiResponse<TimeCapsuleResponseDto>.ErrorResult("您已认领此时间胶囊");
}
// 创建接收邮件记录
var receivedMail = new ReceivedMail
{
SentMailId = timeCapsule.SentMailId,
RecipientId = userId,
ReceivedAt = DateTime.UtcNow
};
_context.ReceivedMails.Add(receivedMail);
await _context.SaveChangesAsync();
var capsuleResponse = await GetTimeCapsuleWithDetailsAsync(timeCapsule.Id);
return ApiResponse<TimeCapsuleResponseDto>.SuccessResult(capsuleResponse, "时间胶囊认领成功");
}
public async Task<ApiResponse<TimeCapsuleViewResponseDto>> GetTimeCapsuleViewAsync(int userId)
{
// 获取用户的所有时间胶囊
var capsules = await _context.TimeCapsules
.Where(tc => tc.UserId == userId)
.Include(tc => tc.SentMail)
.ToListAsync();
// 转换为视图DTO
var capsuleViews = capsules.Select(capsule =>
{
var totalDays = (capsule.SentMail.DeliveryTime - capsule.SentMail.SentAt).TotalDays;
var elapsedDays = (DateTime.UtcNow - capsule.SentMail.SentAt).TotalDays;
var progress = totalDays > 0 ? Math.Min(1, elapsedDays / totalDays) : 0;
return new TimeCapsuleViewDto
{
CapsuleId = capsule.Id,
MailId = capsule.SentMailId,
Title = capsule.SentMail.Title,
SendTime = capsule.SentMail.SentAt,
DeliveryTime = capsule.SentMail.DeliveryTime,
Progress = progress,
Position = new TimeCapsulePosition
{
X = capsule.PositionX,
Y = capsule.PositionY,
Z = capsule.PositionZ
},
Style = capsule.Color ?? "#FFFFFF",
GlowIntensity = capsule.Status == 1 ? 0.8 : 0.3 // 漂浮中的胶囊发光更亮
};
}).ToList();
// 获取用户偏好设置(如果有)
var user = await _context.Users.FindAsync(userId);
var scene = user?.PreferredScene ?? "SPACE";
var background = user?.PreferredBackground ?? "default";
var viewResponse = new TimeCapsuleViewResponseDto
{
Capsules = capsuleViews,
Scene = scene,
Background = background
};
return ApiResponse<TimeCapsuleViewResponseDto>.SuccessResult(viewResponse);
}
public async Task<ApiResponse<TimeCapsuleResponseDto>> UpdateTimeCapsuleStyleAsync(int userId, int capsuleId, TimeCapsuleStyleUpdateDto updateDto)
{
var timeCapsule = await _context.TimeCapsules
.FirstOrDefaultAsync(tc => tc.Id == capsuleId && tc.UserId == userId);
if (timeCapsule == null)
{
return ApiResponse<TimeCapsuleResponseDto>.ErrorResult("时间胶囊不存在");
}
// 检查胶囊是否已开启,已开启的胶囊不能修改
if (timeCapsule.Status >= 3)
{
return ApiResponse<TimeCapsuleResponseDto>.ErrorResult("已开启的时间胶囊不能修改");
}
// 更新胶囊样式
timeCapsule.Color = updateDto.Style;
if (updateDto.GlowIntensity.HasValue)
{
// 将发光强度转换为透明度(反向关系)
timeCapsule.Opacity = 1.0 - (updateDto.GlowIntensity.Value * 0.5);
}
await _context.SaveChangesAsync();
var capsuleResponse = await GetTimeCapsuleWithDetailsAsync(timeCapsule.Id);
return ApiResponse<TimeCapsuleResponseDto>.SuccessResult(capsuleResponse, "时间胶囊样式更新成功");
}
private async Task<TimeCapsuleResponseDto> GetTimeCapsuleWithDetailsAsync(int capsuleId)
{
var timeCapsule = await _context.TimeCapsules
.Include(tc => tc.User)
.Include(tc => tc.SentMail)
.FirstOrDefaultAsync(tc => tc.Id == capsuleId);
return MapToTimeCapsuleResponseDto(timeCapsule!);
}
private static TimeCapsuleResponseDto MapToTimeCapsuleResponseDto(TimeCapsule timeCapsule)
{
var daysUntilDelivery = (int)(timeCapsule.SentMail.DeliveryTime - DateTime.UtcNow).TotalDays;
var distanceFromNow = CalculateDistanceFromNow(daysUntilDelivery);
return new TimeCapsuleResponseDto
{
Id = timeCapsule.Id,
UserId = timeCapsule.UserId,
SentMailId = timeCapsule.SentMailId,
MailTitle = timeCapsule.SentMail.Title,
PositionX = timeCapsule.PositionX,
PositionY = timeCapsule.PositionY,
PositionZ = timeCapsule.PositionZ,
Size = timeCapsule.Size,
Color = timeCapsule.Color,
Opacity = timeCapsule.Opacity,
Rotation = timeCapsule.Rotation,
Status = timeCapsule.Status,
StatusText = GetStatusText(timeCapsule.Status),
Type = timeCapsule.Type,
TypeText = GetTypeText(timeCapsule.Type),
CreatedAt = timeCapsule.CreatedAt,
DeliveryTime = timeCapsule.SentMail.DeliveryTime,
DaysUntilDelivery = daysUntilDelivery,
DistanceFromNow = distanceFromNow
};
}
private static string GetStatusText(int status)
{
return status switch
{
0 => "未激活",
1 => "漂浮中",
2 => "即将到达",
3 => "已开启",
_ => "未知"
};
}
private static string GetTypeText(int type)
{
return type switch
{
0 => "普通",
1 => "特殊",
2 => "限时",
_ => "未知"
};
}
private static double CalculateDistanceFromNow(int daysUntilDelivery)
{
// 简单的距离计算,可以根据需要调整
// 距离"现在"越远,距离值越大
return Math.Max(1, daysUntilDelivery / 30.0); // 以月为单位
}
}
}