using Microsoft.EntityFrameworkCore; using HardwarePerformance.Application.Interfaces; using HardwarePerformance.Core.Entities; using HardwarePerformance.Infrastructure.Data; namespace HardwarePerformance.Infrastructure.Repositories { /// /// 产品Repository实现 /// public class ProductRepository : Repository, IProductRepository { public ProductRepository(AppDbContext context) : base(context) { } public async Task<(IEnumerable products, int totalCount)> GetByCategoryAsync( int categoryId, int pageNumber = 1, int pageSize = 20, string sortBy = "CurrentRank", bool ascending = true) { var query = _dbSet .Include(p => p.Category) .Include(p => p.PerformanceScores) .Where(p => p.CategoryId == categoryId); // 排序 query = ApplySorting(query, sortBy, ascending); var totalCount = await query.CountAsync(); var products = await query .Skip((pageNumber - 1) * pageSize) .Take(pageSize) .ToListAsync(); return (products, totalCount); } public async Task GetByModelAsync(string model) { return await _dbSet .Include(p => p.Category) .Include(p => p.PerformanceScores) .FirstOrDefaultAsync(p => p.Model == model); } public async Task> GetTopNByCategoryAsync(int categoryId, int n) { return await _dbSet .Include(p => p.Category) .Include(p => p.PerformanceScores) .Where(p => p.CategoryId == categoryId) .OrderBy(p => p.CurrentRank) .Take(n) .ToListAsync(); } public async Task<(IEnumerable products, int totalCount)> SearchAsync( string searchTerm, int? categoryId = null, int pageNumber = 1, int pageSize = 20) { var query = _dbSet .Include(p => p.Category) .Include(p => p.PerformanceScores) .Where(p => (string.IsNullOrEmpty(searchTerm) || p.Name.Contains(searchTerm) || p.Model.Contains(searchTerm) || p.Manufacturer.Contains(searchTerm)) && (!categoryId.HasValue || p.CategoryId == categoryId.Value)); var totalCount = await query.CountAsync(); var products = await query .OrderBy(p => p.CurrentRank) .Skip((pageNumber - 1) * pageSize) .Take(pageSize) .ToListAsync(); return (products, totalCount); } public async Task<(IEnumerable products, int totalCount)> FilterAsync( int categoryId, int? minScore = null, int? maxScore = null, int? minYear = null, int? maxYear = null, string? manufacturer = null, int pageNumber = 1, int pageSize = 20) { var query = _dbSet .Include(p => p.Category) .Include(p => p.PerformanceScores) .Where(p => p.CategoryId == categoryId); // 性能分数筛选 if (minScore.HasValue) { query = query.Where(p => p.PerformanceScores.Any(ps => ps.Score >= minScore.Value)); } if (maxScore.HasValue) { query = query.Where(p => p.PerformanceScores.Any(ps => ps.Score <= maxScore.Value)); } // 发布年份筛选 if (minYear.HasValue) { query = query.Where(p => p.ReleaseDate.HasValue && p.ReleaseDate.Value.Year >= minYear.Value); } if (maxYear.HasValue) { query = query.Where(p => p.ReleaseDate.HasValue && p.ReleaseDate.Value.Year <= maxYear.Value); } // 品牌筛选 if (!string.IsNullOrEmpty(manufacturer)) { query = query.Where(p => p.Manufacturer == manufacturer); } var totalCount = await query.CountAsync(); var products = await query .OrderBy(p => p.CurrentRank) .Skip((pageNumber - 1) * pageSize) .Take(pageSize) .ToListAsync(); return (products, totalCount); } public async Task GetWithDetailsAsync(int id) { return await _dbSet .Include(p => p.Category) .Include(p => p.Specifications) .Include(p => p.PerformanceScores) .ThenInclude(ps => ps.DataSource) .Include(p => p.RankingHistories .OrderByDescending(rh => rh.RecordDate) .Take(12)) // 最近12个月的排名历史 .FirstOrDefaultAsync(p => p.Id == id); } public async Task> GetByIdsAsync(IEnumerable productIds) { return await _dbSet .Include(p => p.Category) .Include(p => p.Specifications) .Include(p => p.PerformanceScores) .ThenInclude(ps => ps.DataSource) .Where(p => productIds.Contains(p.Id)) .ToListAsync(); } public async Task> GetManufacturersAsync(int? categoryId = null) { var query = _dbSet.AsQueryable(); if (categoryId.HasValue) { query = query.Where(p => p.CategoryId == categoryId.Value); } return await query .Where(p => !string.IsNullOrEmpty(p.Manufacturer)) .Select(p => p.Manufacturer) .Distinct() .OrderBy(m => m) .ToListAsync(); } public async Task> GetRankingHistoryAsync(int productId, int months = 12) { var startDate = DateTime.UtcNow.AddMonths(-months); return await _context.RankingHistories .Where(rh => rh.ProductId == productId && rh.RecordDate >= startDate) .OrderBy(rh => rh.RecordDate) .ToListAsync(); } public async Task<(IEnumerable products, int totalCount)> GetByManufacturerAsync( string manufacturer, int? categoryId = null, int pageNumber = 1, int pageSize = 20) { var query = _dbSet .Include(p => p.Category) .Include(p => p.PerformanceScores) .Where(p => p.Manufacturer == manufacturer); if (categoryId.HasValue) { query = query.Where(p => p.CategoryId == categoryId.Value); } var totalCount = await query.CountAsync(); var products = await query .OrderBy(p => p.CurrentRank) .Skip((pageNumber - 1) * pageSize) .Take(pageSize) .ToListAsync(); return (products, totalCount); } private IQueryable ApplySorting(IQueryable query, string sortBy, bool ascending) { return sortBy.ToLower() switch { "name" => ascending ? query.OrderBy(p => p.Name) : query.OrderByDescending(p => p.Name), "manufacturer" => ascending ? query.OrderBy(p => p.Manufacturer) : query.OrderByDescending(p => p.Manufacturer), "releasedate" => ascending ? query.OrderBy(p => p.ReleaseDate) : query.OrderByDescending(p => p.ReleaseDate), "currentrank" => ascending ? query.OrderBy(p => p.CurrentRank) : query.OrderByDescending(p => p.CurrentRank), "score" => ascending ? query.OrderBy(p => p.PerformanceScores.Any() ? p.PerformanceScores.Average(ps => ps.Score) : 0) : query.OrderByDescending(p => p.PerformanceScores.Any() ? p.PerformanceScores.Average(ps => ps.Score) : 0), _ => ascending ? query.OrderBy(p => p.CurrentRank) : query.OrderByDescending(p => p.CurrentRank) }; } } }