初始化
This commit is contained in:
419
FutureMailAPI/Services/PersonalSpaceService.cs
Normal file
419
FutureMailAPI/Services/PersonalSpaceService.cs
Normal file
@@ -0,0 +1,419 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user