436 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			436 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| 
								 | 
							
								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); // 以月为单位
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |