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

419 lines
17 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<PersonalSpaceService> _logger;
public PersonalSpaceService(FutureMailDbContext context, ILogger<PersonalSpaceService> logger)
{
_context = context;
_logger = logger;
}
public async Task<ApiResponse<TimelineResponseDto>> GetTimelineAsync(int userId, TimelineQueryDto query)
{
try
{
var response = new TimelineResponseDto();
var timelineDict = new Dictionary<string, TimelineDateDto>();
// 获取发送的邮件
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<TimelineEventDto>()
};
}
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<TimelineEventDto>()
};
}
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<TimelineResponseDto>.SuccessResult(response);
}
catch (Exception ex)
{
_logger.LogError(ex, "获取时间线时发生错误");
return ApiResponse<TimelineResponseDto>.ErrorResult("获取时间线失败");
}
}
public async Task<ApiResponse<StatisticsResponseDto>> 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<StatisticsResponseDto>.SuccessResult(response);
}
catch (Exception ex)
{
_logger.LogError(ex, "获取统计数据时发生错误");
return ApiResponse<StatisticsResponseDto>.ErrorResult("获取统计数据失败");
}
}
public async Task<ApiResponse<SubscriptionResponseDto>> GetSubscriptionAsync(int userId)
{
try
{
// 在实际应用中,这里会从数据库或订阅服务中获取用户的订阅信息
// 目前我们使用模拟数据
var user = await _context.Users
.FirstOrDefaultAsync(u => u.Id == userId);
if (user == null)
{
return ApiResponse<SubscriptionResponseDto>.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<SubscriptionResponseDto>.SuccessResult(response);
}
catch (Exception ex)
{
_logger.LogError(ex, "获取订阅信息时发生错误");
return ApiResponse<SubscriptionResponseDto>.ErrorResult("获取订阅信息失败");
}
}
public async Task<ApiResponse<UserProfileResponseDto>> GetUserProfileAsync(int userId)
{
try
{
var user = await _context.Users
.FirstOrDefaultAsync(u => u.Id == userId);
if (user == null)
{
return ApiResponse<UserProfileResponseDto>.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<UserProfileResponseDto>.SuccessResult(response);
}
catch (Exception ex)
{
_logger.LogError(ex, "获取用户资料时发生错误");
return ApiResponse<UserProfileResponseDto>.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<KeywordCloudDto> GenerateKeywordCloud(List<string> contents)
{
// 简单的关键词提取
var allWords = new List<string>();
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<MonthlyStatsDto> GenerateMonthlyStats(List<SentMail> sentMails, List<ReceivedMail> receivedMails)
{
var monthlyStats = new Dictionary<string, MonthlyStatsDto>();
// 处理发送的邮件
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();
}
}
}