using HoneyBox.Core.Interfaces; using HoneyBox.Model.Data; using HoneyBox.Model.Models.Rank; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; namespace HoneyBox.Core.Services; /// /// 排行榜服务实现 /// public class RankService : IRankService { private readonly HoneyBoxDbContext _dbContext; private readonly ILogger _logger; /// /// 有效的排行榜类型 /// private static readonly HashSet ValidRankTypes = new(StringComparer.OrdinalIgnoreCase) { "diamond", "integral", "dadajuan", "invite", "loss" }; public RankService(HoneyBoxDbContext dbContext, ILogger logger) { _dbContext = dbContext; _logger = logger; } /// public async Task GetWeekRankAsync(int userId) { // 获取当前用户信息 var user = await _dbContext.Users .Where(u => u.Id == userId) .Select(u => new { u.Nickname, u.HeadImg }) .FirstOrDefaultAsync(); if (user == null) { throw new InvalidOperationException("用户不存在"); } // 计算本周时间范围(周一到周日) var (weekStart, weekEnd) = GetWeekRange(DateTime.Now); var weekStartTimestamp = ToUnixTimestamp(weekStart); var weekEndTimestamp = ToUnixTimestamp(weekEnd); // 查询当前用户本周消费总额 var myOrderTotal = await _dbContext.Orders .Where(o => o.UserId == userId && o.Addtime >= weekStartTimestamp && o.Addtime <= weekEndTimestamp && o.Status == 1 && o.OrderType < 5) .SumAsync(o => (decimal?)o.OrderTotal) ?? 0; // 查询排行榜前30名 var rankData = await _dbContext.Orders .Where(o => o.Addtime >= weekStartTimestamp && o.Addtime <= weekEndTimestamp && o.Status == 1 && o.OrderType < 5) .GroupBy(o => o.UserId) .Select(g => new { UserId = g.Key, OrderTotal = g.Sum(o => o.OrderTotal) }) .OrderByDescending(x => x.OrderTotal) .ThenBy(x => x.UserId) .Take(30) .ToListAsync(); // 获取用户信息 var userIds = rankData.Select(r => r.UserId).ToList(); var users = await _dbContext.Users .Where(u => userIds.Contains(u.Id)) .Select(u => new { u.Id, u.Nickname, u.HeadImg }) .ToDictionaryAsync(u => u.Id); // 获取周榜奖品信息 (goods_id = -1 表示周榜奖品) var prizes = await _dbContext.GoodsItems .Where(g => g.GoodsId == -1 && g.Rank >= 1 && g.Rank <= 30) .Select(g => new { g.Rank, g.Title, g.ImgUrl }) .ToDictionaryAsync(g => g.Rank); // 构建排行榜数据 var data = new List(); object myRank = "暂未上榜"; object myPrizeTitle = 0; object myPrizeImgurl = 0; for (int i = 0; i < rankData.Count; i++) { var item = rankData[i]; var rank = i + 1; var userInfo = users.GetValueOrDefault(item.UserId); var prizeInfo = prizes.GetValueOrDefault(rank); var rankItem = new RankItemDto { Rank = rank, UserId = item.UserId, Nickname = userInfo?.Nickname ?? "", Headimg = userInfo?.HeadImg ?? "", OrderTotal = item.OrderTotal, PrizeTitle = prizeInfo?.Title ?? "", PrizeImgurl = prizeInfo?.ImgUrl ?? "" }; data.Add(rankItem); // 判断当前用户是否在排名中 if (item.UserId == userId) { myRank = rank; myPrizeTitle = prizeInfo?.Title ?? ""; myPrizeImgurl = prizeInfo?.ImgUrl ?? ""; } } return new RankResponse { Date = $"{weekStart:MM月dd日}-{weekEnd:MM月dd日}", EndDate = weekEndTimestamp, MyRank = new MyRankDto { MyRank = myRank, MyPrizeTitle = myPrizeTitle, MyPrizeImgurl = myPrizeImgurl, MyOrderTotal = myOrderTotal, MyNickname = user.Nickname, MyHeadimg = user.HeadImg }, Data = data }; } /// public async Task GetMonthRankAsync(int userId) { // 获取当前用户信息 var user = await _dbContext.Users .Where(u => u.Id == userId) .Select(u => new { u.Nickname, u.HeadImg }) .FirstOrDefaultAsync(); if (user == null) { throw new InvalidOperationException("用户不存在"); } // 计算本月时间范围 var (monthStart, monthEnd) = GetMonthRange(DateTime.Now); var monthStartTimestamp = ToUnixTimestamp(monthStart); var monthEndTimestamp = ToUnixTimestamp(monthEnd); // 查询当前用户本月消费总额 var myOrderTotal = await _dbContext.Orders .Where(o => o.UserId == userId && o.Addtime >= monthStartTimestamp && o.Addtime <= monthEndTimestamp && o.Status == 1 && o.OrderType < 5) .SumAsync(o => (decimal?)o.OrderTotal) ?? 0; // 查询排行榜前30名 var rankData = await _dbContext.Orders .Where(o => o.Addtime >= monthStartTimestamp && o.Addtime <= monthEndTimestamp && o.Status == 1 && o.OrderType < 5) .GroupBy(o => o.UserId) .Select(g => new { UserId = g.Key, OrderTotal = g.Sum(o => o.OrderTotal) }) .OrderByDescending(x => x.OrderTotal) .ThenBy(x => x.UserId) .Take(30) .ToListAsync(); // 获取用户信息 var userIds = rankData.Select(r => r.UserId).ToList(); var users = await _dbContext.Users .Where(u => userIds.Contains(u.Id)) .Select(u => new { u.Id, u.Nickname, u.HeadImg }) .ToDictionaryAsync(u => u.Id); // 获取月榜奖品信息 (goods_id = -2 表示月榜奖品) var prizes = await _dbContext.GoodsItems .Where(g => g.GoodsId == -2 && g.Rank >= 1 && g.Rank <= 30) .Select(g => new { g.Rank, g.Title, g.ImgUrl }) .ToDictionaryAsync(g => g.Rank); // 构建排行榜数据 var data = new List(); object myRank = "暂未上榜"; object myPrizeTitle = 0; object myPrizeImgurl = 0; for (int i = 0; i < rankData.Count; i++) { var item = rankData[i]; var rank = i + 1; var userInfo = users.GetValueOrDefault(item.UserId); var prizeInfo = prizes.GetValueOrDefault(rank); var rankItem = new RankItemDto { Rank = rank, UserId = item.UserId, Nickname = userInfo?.Nickname ?? "", Headimg = userInfo?.HeadImg ?? "", OrderTotal = item.OrderTotal, PrizeTitle = prizeInfo?.Title ?? "", PrizeImgurl = prizeInfo?.ImgUrl ?? "" }; data.Add(rankItem); // 判断当前用户是否在排名中 if (item.UserId == userId) { myRank = rank; myPrizeTitle = prizeInfo?.Title ?? ""; myPrizeImgurl = prizeInfo?.ImgUrl ?? ""; } } return new RankResponse { Date = $"{monthStart:MM月dd日}-{monthEnd:MM月dd日}", EndDate = monthEndTimestamp, MyRank = new MyRankDto { MyRank = myRank, MyPrizeTitle = myPrizeTitle, MyPrizeImgurl = myPrizeImgurl, MyOrderTotal = myOrderTotal, MyNickname = user.Nickname, MyHeadimg = user.HeadImg }, Data = data }; } /// /// 获取本周时间范围(周一00:00:00到周日23:59:59) /// private static (DateTime start, DateTime end) GetWeekRange(DateTime date) { // 获取当前是周几 (0=周日, 1=周一, ..., 6=周六) var dayOfWeek = (int)date.DayOfWeek; // 计算到周一的天数差 var daysToMonday = dayOfWeek == 0 ? 6 : dayOfWeek - 1; // 本周一00:00:00 var weekStart = date.Date.AddDays(-daysToMonday); // 本周日23:59:59 var weekEnd = weekStart.AddDays(6).AddHours(23).AddMinutes(59).AddSeconds(59); return (weekStart, weekEnd); } /// /// 获取本月时间范围(1号00:00:00到月末23:59:59) /// private static (DateTime start, DateTime end) GetMonthRange(DateTime date) { // 本月1号00:00:00 var monthStart = new DateTime(date.Year, date.Month, 1, 0, 0, 0); // 本月最后一天23:59:59 var daysInMonth = DateTime.DaysInMonth(date.Year, date.Month); var monthEnd = new DateTime(date.Year, date.Month, daysInMonth, 23, 59, 59); return (monthStart, monthEnd); } /// /// 将DateTime转换为Unix时间戳 /// private static int ToUnixTimestamp(DateTime dateTime) { return (int)(dateTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; } /// public async Task> GetRankListAsync(string type, int page = 1, int limit = 10) { if (!ValidRankTypes.Contains(type)) { throw new InvalidOperationException("无效的排行榜类型"); } return type.ToLower() switch { "diamond" => await GetDiamondRankAsync(page, limit), "integral" => await GetIntegralRankAsync(page, limit), "dadajuan" => await GetDadajuanRankAsync(page, limit), "invite" => await GetInviteRankAsync(page, limit), "loss" => await GetLossRankAsync(page, limit), _ => new List() }; } /// public async Task GetConsumeRecordAsync(int page = 1, int limit = 10) { // 获取本月时间范围 var (monthStart, monthEnd) = GetMonthRange(DateTime.Now); var monthStartTimestamp = ToUnixTimestamp(monthStart); var monthEndTimestamp = ToUnixTimestamp(monthEnd); // 查询本月消费排行榜 var rankData = await _dbContext.Orders .Where(o => o.Status == 1 && o.Price > 0 && o.Addtime >= monthStartTimestamp && o.Addtime <= monthEndTimestamp) .GroupBy(o => o.UserId) .Select(g => new { UserId = g.Key, Price = g.Sum(o => o.Price) }) .OrderByDescending(x => x.Price) .Skip((page - 1) * limit) .Take(limit) .ToListAsync(); // 获取用户信息 var userIds = rankData.Select(r => r.UserId).ToList(); var users = await _dbContext.Users .Where(u => userIds.Contains(u.Id)) .Select(u => new { u.Id, u.Nickname, u.HeadImg, u.Mobile }) .ToDictionaryAsync(u => u.Id); // 构建响应数据 var list = rankData.Select(item => { var userInfo = users.GetValueOrDefault(item.UserId); return new ConsumeRecordItemDto { UserId = item.UserId, Nickname = userInfo?.Nickname ?? "", Headimg = userInfo?.HeadImg ?? "", Mobile = userInfo?.Mobile ?? "", Price = item.Price }; }).ToList(); return new ConsumeRecordResponse { List = list }; } #region Private Rank Methods /// /// 获取钻石排行榜 /// private async Task> GetDiamondRankAsync(int page, int limit) { // 获取测试用户ID列表 var testUserIds = await _dbContext.Users .Where(u => u.IsTest > 0 && u.Status == 1) .Select(u => u.Id) .ToListAsync(); // 查询钻石消费排行 var rankData = await _dbContext.Orders .Where(o => o.Status == 1 && o.UseMoney > 0 && !testUserIds.Contains(o.UserId)) .GroupBy(o => o.UserId) .Select(g => new { UserId = g.Key, Value = g.Sum(o => o.UseMoney) }) .OrderByDescending(x => x.Value) .Skip((page - 1) * limit) .Take(limit) .ToListAsync(); return await BuildRankListAsync(rankData, page, limit, "钻石"); } /// /// 获取UU币排行榜 /// private async Task> GetIntegralRankAsync(int page, int limit) { // 获取测试用户ID列表 var testUserIds = await _dbContext.Users .Where(u => u.IsTest > 0 && u.Status == 1) .Select(u => u.Id) .ToListAsync(); // 查询积分消费排行 var rankData = await _dbContext.Orders .Where(o => o.Status == 1 && o.UseIntegral > 0 && !testUserIds.Contains(o.UserId)) .GroupBy(o => o.UserId) .Select(g => new { UserId = g.Key, Value = g.Sum(o => o.UseIntegral) }) .OrderByDescending(x => x.Value) .Skip((page - 1) * limit) .Take(limit) .ToListAsync(); return await BuildRankListAsync(rankData, page, limit, "UU币"); } /// /// 获取达达卷排行榜 /// private async Task> GetDadajuanRankAsync(int page, int limit) { // 达达卷排行榜默认显示更多数据 var actualLimit = limit == 10 ? 200 : limit; // 获取测试用户ID列表 var testUserIds = await _dbContext.Users .Where(u => u.IsTest > 0 && u.Status == 1) .Select(u => u.Id) .ToListAsync(); // 查询达达卷回收排行 var rankData = await _dbContext.OrderItemsRecoveries .Where(o => o.Money > 0 && !testUserIds.Contains(o.UserId)) .GroupBy(o => o.UserId) .Select(g => new { UserId = g.Key, Value = g.Sum(o => o.Money) * 100 // 转换为达达卷单位 }) .OrderByDescending(x => x.Value) .Skip((page - 1) * actualLimit) .Take(actualLimit) .ToListAsync(); return await BuildRankListAsync(rankData, page, actualLimit, "达达卷"); } /// /// 获取邀请排行榜 /// private async Task> GetInviteRankAsync(int page, int limit) { // 邀请排行榜默认显示更多数据 var actualLimit = limit == 10 ? 50 : limit; // 查询邀请排行 var rankData = await _dbContext.Users .Where(u => u.Pid > 0 && u.IsTest == 0 && u.Status == 1) .GroupBy(u => u.Pid) .Select(g => new { UserId = g.Key, Value = (decimal)g.Count() }) .Where(x => x.Value > 0) .OrderByDescending(x => x.Value) .Skip((page - 1) * actualLimit) .Take(actualLimit) .ToListAsync(); return await BuildRankListAsync(rankData, page, actualLimit, "人"); } /// /// 获取亏损排行榜 /// private async Task> GetLossRankAsync(int page, int limit) { // 获取测试用户ID列表 var testUserIds = await _dbContext.Users .Where(u => u.IsTest > 0) .Select(u => u.Id) .ToListAsync(); // 查询订单消费数据 var orderData = await _dbContext.Orders .Where(o => o.Status == 1 && !testUserIds.Contains(o.UserId)) .GroupBy(o => o.UserId) .Select(g => new { UserId = g.Key, ConsumeMoney = g.Sum(o => o.Price) }) .ToListAsync(); // 获取所有相关用户ID var userIds = orderData.Select(o => o.UserId).ToList(); // 查询出货金额 var outputData = await _dbContext.OrderItems .Where(o => userIds.Contains(o.UserId)) .GroupBy(o => o.UserId) .Select(g => new { UserId = g.Key, OutputMoney = g.Sum(o => o.GoodslistMoney) }) .ToDictionaryAsync(x => x.UserId, x => x.OutputMoney); // 查询达达卷金额 var dadaData = await _dbContext.OrderItemsRecoveries .Where(o => userIds.Contains(o.UserId)) .GroupBy(o => o.UserId) .Select(g => new { UserId = g.Key, DadaMoney = g.Sum(o => o.Money) }) .ToDictionaryAsync(x => x.UserId, x => x.DadaMoney); // 计算亏损并排序 var lossData = orderData .Select(o => { var outputMoney = outputData.GetValueOrDefault(o.UserId, 0); var dadaMoney = dadaData.GetValueOrDefault(o.UserId, 0); var lossMoney = outputMoney - (o.ConsumeMoney + dadaMoney); return new { o.UserId, LossMoney = lossMoney }; }) .Where(x => x.LossMoney < 0) // 只显示亏损用户 .OrderBy(x => x.LossMoney) // 亏损越多排名越前 .Skip((page - 1) * limit) .Take(limit) .ToList(); // 获取用户信息 var lossUserIds = lossData.Select(x => x.UserId).ToList(); var users = await _dbContext.Users .Where(u => lossUserIds.Contains(u.Id)) .Select(u => new { u.Id, u.Nickname, u.HeadImg }) .ToDictionaryAsync(u => u.Id); // 构建排行榜数据 var result = new List(); var offset = (page - 1) * limit; for (int i = 0; i < lossData.Count; i++) { var item = lossData[i]; var userInfo = users.GetValueOrDefault(item.UserId); if (userInfo != null) { result.Add(new GenericRankItemDto { Rank = offset + i + 1, UserId = item.UserId, Nickname = userInfo.Nickname ?? "", Headimg = userInfo.HeadImg ?? "", Value = Math.Abs(item.LossMoney), // 显示亏损金额的绝对值 Unit = "元" }); } } return result; } /// /// 构建排行榜列表 /// private async Task> BuildRankListAsync( List rankData, int page, int limit, string unit) where T : class { // 使用反射获取UserId和Value属性 var userIdProp = typeof(T).GetProperty("UserId"); var valueProp = typeof(T).GetProperty("Value"); if (userIdProp == null || valueProp == null) { return new List(); } var userIds = rankData.Select(r => (int)userIdProp.GetValue(r)!).ToList(); var users = await _dbContext.Users .Where(u => userIds.Contains(u.Id)) .Select(u => new { u.Id, u.Nickname, u.HeadImg }) .ToDictionaryAsync(u => u.Id); var result = new List(); var offset = (page - 1) * limit; for (int i = 0; i < rankData.Count; i++) { var item = rankData[i]; var userId = (int)userIdProp.GetValue(item)!; var value = Convert.ToDecimal(valueProp.GetValue(item)); var userInfo = users.GetValueOrDefault(userId); if (userInfo != null) { result.Add(new GenericRankItemDto { Rank = offset + i + 1, UserId = userId, Nickname = userInfo.Nickname ?? "", Headimg = userInfo.HeadImg ?? "", Value = value, Unit = unit }); } } return result; } #endregion }