using Microsoft.EntityFrameworkCore; using FutureMailAPI.Data; using FutureMailAPI.Models; using FutureMailAPI.DTOs; using System.Text.Json; namespace FutureMailAPI.Services { public class PersonalSpaceService : IPersonalSpaceService { private readonly FutureMailDbContext _context; private readonly ILogger _logger; public PersonalSpaceService(FutureMailDbContext context, ILogger logger) { _context = context; _logger = logger; } public async Task> GetTimelineAsync(int userId, TimelineQueryDto query) { try { var response = new TimelineResponseDto(); var timelineDict = new Dictionary(); // 获取发送的邮件 if (query.Type == TimelineType.ALL || query.Type == TimelineType.SENT) { var sentMailsQuery = _context.SentMails .Where(m => m.SenderId == userId) .Include(m => m.Recipient) .AsQueryable(); if (query.StartDate.HasValue) { sentMailsQuery = sentMailsQuery.Where(m => m.SentAt >= query.StartDate.Value); } if (query.EndDate.HasValue) { sentMailsQuery = sentMailsQuery.Where(m => m.SentAt <= query.EndDate.Value); } var sentMails = await sentMailsQuery .OrderBy(m => m.SentAt) .ToListAsync(); foreach (var mail in sentMails) { var dateKey = mail.SentAt.ToString("yyyy-MM-dd"); if (!timelineDict.ContainsKey(dateKey)) { timelineDict[dateKey] = new TimelineDateDto { Date = dateKey, Events = new List() }; } var recipientName = mail.Recipient?.Username ?? "自己"; var recipientAvatar = mail.Recipient?.Avatar; timelineDict[dateKey].Events.Add(new TimelineEventDto { Type = TimelineEventType.SENT, MailId = mail.Id, Title = mail.Title, Time = mail.SentAt.ToString("HH:mm"), WithUser = new UserInfoDto { UserId = mail.RecipientId ?? 0, Username = recipientName, Avatar = recipientAvatar }, Emotion = AnalyzeMailEmotion(mail.Content) }); } } // 获取接收的邮件 if (query.Type == TimelineType.ALL || query.Type == TimelineType.RECEIVED) { var receivedMailsQuery = _context.ReceivedMails .Where(r => r.RecipientId == userId) .Include(r => r.SentMail) .ThenInclude(m => m.Sender) .AsQueryable(); if (query.StartDate.HasValue) { receivedMailsQuery = receivedMailsQuery.Where(r => r.ReceivedAt >= query.StartDate.Value); } if (query.EndDate.HasValue) { receivedMailsQuery = receivedMailsQuery.Where(r => r.ReceivedAt <= query.EndDate.Value); } var receivedMails = await receivedMailsQuery .OrderBy(r => r.ReceivedAt) .ToListAsync(); foreach (var receivedMail in receivedMails) { var dateKey = receivedMail.ReceivedAt.ToString("yyyy-MM-dd"); if (!timelineDict.ContainsKey(dateKey)) { timelineDict[dateKey] = new TimelineDateDto { Date = dateKey, Events = new List() }; } var senderName = receivedMail.SentMail.Sender.Username; var senderAvatar = receivedMail.SentMail.Sender.Avatar; timelineDict[dateKey].Events.Add(new TimelineEventDto { Type = TimelineEventType.RECEIVED, MailId = receivedMail.SentMailId, Title = receivedMail.SentMail.Title, Time = receivedMail.ReceivedAt.ToString("HH:mm"), WithUser = new UserInfoDto { UserId = receivedMail.SentMail.SenderId, Username = senderName, Avatar = senderAvatar }, Emotion = AnalyzeMailEmotion(receivedMail.SentMail.Content) }); } } // 对每个日期的事件按时间排序 foreach (var dateEntry in timelineDict) { dateEntry.Value.Events = dateEntry.Value.Events .OrderBy(e => e.Time) .ToList(); } // 按日期排序 response.Timeline = timelineDict .OrderBy(kvp => kvp.Key) .Select(kvp => kvp.Value) .ToList(); return ApiResponse.SuccessResult(response); } catch (Exception ex) { _logger.LogError(ex, "获取时间线时发生错误"); return ApiResponse.ErrorResult("获取时间线失败"); } } public async Task> GetStatisticsAsync(int userId) { try { var response = new StatisticsResponseDto(); // 获取发送的邮件统计 var sentMails = await _context.SentMails .Where(m => m.SenderId == userId) .ToListAsync(); response.TotalSent = sentMails.Count; // 获取接收的邮件统计 var receivedMails = await _context.ReceivedMails .Where(r => r.RecipientId == userId) .Include(r => r.SentMail) .ThenInclude(m => m.Sender) .ToListAsync(); response.TotalReceived = receivedMails.Count; // 计算时间旅行时长(天) if (sentMails.Any()) { var earliestDelivery = sentMails.Min(m => m.DeliveryTime); var latestDelivery = sentMails.Max(m => m.DeliveryTime); response.TimeTravelDuration = (latestDelivery - earliestDelivery).Days; } // 找出最频繁的收件人 var recipientCounts = sentMails .Where(m => m.RecipientId.HasValue) .GroupBy(m => m.RecipientId) .Select(g => new { RecipientId = g.Key, Count = g.Count() }) .OrderByDescending(g => g.Count) .FirstOrDefault(); if (recipientCounts != null) { var recipient = await _context.Users .FirstOrDefaultAsync(u => u.Id == recipientCounts.RecipientId); response.MostFrequentRecipient = recipient?.Username ?? "未知用户"; } // 找出最常见的年份(投递年份) if (sentMails.Any()) { var yearCounts = sentMails .GroupBy(m => m.DeliveryTime.Year) .Select(g => new { Year = g.Key, Count = g.Count() }) .OrderByDescending(g => g.Count) .FirstOrDefault(); response.MostCommonYear = yearCounts?.Year ?? DateTime.Now.Year; } // 生成关键词云 var allContents = sentMails.Select(m => m.Content).ToList(); allContents.AddRange(receivedMails.Select(r => r.SentMail.Content)); response.KeywordCloud = GenerateKeywordCloud(allContents); // 生成月度统计 response.MonthlyStats = GenerateMonthlyStats(sentMails, receivedMails); return ApiResponse.SuccessResult(response); } catch (Exception ex) { _logger.LogError(ex, "获取统计数据时发生错误"); return ApiResponse.ErrorResult("获取统计数据失败"); } } public async Task> GetSubscriptionAsync(int userId) { try { // 在实际应用中,这里会从数据库或订阅服务中获取用户的订阅信息 // 目前我们使用模拟数据 var user = await _context.Users .FirstOrDefaultAsync(u => u.Id == userId); if (user == null) { return ApiResponse.ErrorResult("用户不存在"); } // 模拟订阅数据 var response = new SubscriptionResponseDto { Plan = SubscriptionPlan.FREE, // 默认为免费计划 RemainingMails = 10 - await _context.SentMails.CountAsync(m => m.SenderId == userId && m.SentAt.Month == DateTime.Now.Month), MaxAttachmentSize = 5 * 1024 * 1024, // 5MB Features = new SubscriptionFeaturesDto { AdvancedTriggers = false, CustomCapsules = false, AIAssistant = true, UnlimitedStorage = false, PriorityDelivery = false }, ExpireDate = null // 免费计划没有过期时间 }; // 如果用户创建时间超过30天,可以升级为高级用户(模拟) if (user.CreatedAt.AddDays(30) < DateTime.UtcNow) { response.Plan = SubscriptionPlan.PREMIUM; response.RemainingMails = 100; response.MaxAttachmentSize = 50 * 1024 * 1024; // 50MB response.Features.AdvancedTriggers = true; response.Features.CustomCapsules = true; response.Features.UnlimitedStorage = true; response.ExpireDate = DateTime.UtcNow.AddMonths(1); } return ApiResponse.SuccessResult(response); } catch (Exception ex) { _logger.LogError(ex, "获取订阅信息时发生错误"); return ApiResponse.ErrorResult("获取订阅信息失败"); } } public async Task> GetUserProfileAsync(int userId) { try { var user = await _context.Users .FirstOrDefaultAsync(u => u.Id == userId); if (user == null) { return ApiResponse.ErrorResult("用户不存在"); } // 获取订阅信息 var subscriptionResult = await GetSubscriptionAsync(userId); var response = new UserProfileResponseDto { Id = user.Id, Username = user.Username, Email = user.Email, Nickname = user.Nickname, Avatar = user.Avatar, CreatedAt = user.CreatedAt, LastLoginAt = user.LastLoginAt, Subscription = subscriptionResult.Data ?? new SubscriptionResponseDto() }; return ApiResponse.SuccessResult(response); } catch (Exception ex) { _logger.LogError(ex, "获取用户资料时发生错误"); return ApiResponse.ErrorResult("获取用户资料失败"); } } private string AnalyzeMailEmotion(string content) { // 简单的情感分析 var positiveKeywords = new[] { "开心", "快乐", "爱", "美好", "成功", "希望", "感谢", "幸福" }; var negativeKeywords = new[] { "悲伤", "难过", "失败", "痛苦", "失望", "愤怒", "焦虑", "恐惧" }; var positiveCount = positiveKeywords.Count(keyword => content.Contains(keyword)); var negativeCount = negativeKeywords.Count(keyword => content.Contains(keyword)); if (positiveCount > negativeCount) return "积极"; else if (negativeCount > positiveCount) return "消极"; else return "中性"; } private List GenerateKeywordCloud(List contents) { // 简单的关键词提取 var allWords = new List(); foreach (var content in contents) { var words = content.Split(new[] { ' ', ',', '.', '!', '?', ';', ':', ',', '。', '!', '?', ';', ':' }, StringSplitOptions.RemoveEmptyEntries); allWords.AddRange(words.Where(word => word.Length > 3)); } var wordCounts = allWords .GroupBy(word => word) .Select(g => new { Word = g.Key, Count = g.Count() }) .OrderByDescending(g => g.Count) .Take(20) .ToList(); var maxCount = wordCounts.FirstOrDefault()?.Count ?? 1; return wordCounts.Select(w => new KeywordCloudDto { Word = w.Word, Count = w.Count, Size = (int)((double)w.Count / maxCount * 10) + 1 // 1-10的大小 }).ToList(); } private List GenerateMonthlyStats(List sentMails, List receivedMails) { var monthlyStats = new Dictionary(); // 处理发送的邮件 foreach (var mail in sentMails) { var monthKey = mail.SentAt.ToString("yyyy-MM"); if (!monthlyStats.ContainsKey(monthKey)) { monthlyStats[monthKey] = new MonthlyStatsDto { Month = monthKey, Sent = 0, Received = 0 }; } monthlyStats[monthKey].Sent++; } // 处理接收的邮件 foreach (var receivedMail in receivedMails) { var monthKey = receivedMail.ReceivedAt.ToString("yyyy-MM"); if (!monthlyStats.ContainsKey(monthKey)) { monthlyStats[monthKey] = new MonthlyStatsDto { Month = monthKey, Sent = 0, Received = 0 }; } monthlyStats[monthKey].Received++; } // 按月份排序,只返回最近12个月的数据 return monthlyStats .OrderBy(kvp => kvp.Key) .TakeLast(12) .Select(kvp => kvp.Value) .ToList(); } } }