271 lines
9.8 KiB
C#
271 lines
9.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using MinimalAPI.Data;
|
|
using MinimalAPI.Models;
|
|
using MinimalAPI.Models.DTOs;
|
|
|
|
namespace MinimalAPI.Services
|
|
{
|
|
public class ComparisonService : IComparisonService
|
|
{
|
|
private readonly AppDbContext _context;
|
|
private readonly IMapper _mapper;
|
|
|
|
public ComparisonService(AppDbContext context, IMapper mapper)
|
|
{
|
|
_context = context;
|
|
_mapper = mapper;
|
|
}
|
|
|
|
public async Task<object> CompareProductsAsync(List<int> productIds)
|
|
{
|
|
// 验证输入
|
|
if (productIds == null || productIds.Count < 2 || productIds.Count > 4)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// 获取产品
|
|
var products = await _context.Products
|
|
.Include(p => p.Category)
|
|
.Where(p => productIds.Contains(p.Id))
|
|
.ToListAsync();
|
|
|
|
if (products.Count != productIds.Count)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// 检查是否所有产品属于同一类别
|
|
var categoryIds = products.Select(p => p.CategoryId).Distinct().ToList();
|
|
if (categoryIds.Count > 1)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// 获取性能分数
|
|
var productIdsList = products.Select(p => p.Id).ToList();
|
|
var performanceScores = await _context.PerformanceScores
|
|
.Where(ps => productIdsList.Contains(ps.ProductId))
|
|
.ToListAsync();
|
|
|
|
// 获取规格参数
|
|
var specifications = await _context.Specifications
|
|
.Where(s => productIdsList.Contains(s.ProductId))
|
|
.ToListAsync();
|
|
|
|
// 创建产品DTO列表
|
|
var productDtos = products.Select(p => {
|
|
var dto = _mapper.Map<ProductDto>(p);
|
|
dto.PerformanceScores = performanceScores
|
|
.Where(ps => ps.ProductId == p.Id)
|
|
.ToList();
|
|
dto.Specifications = specifications
|
|
.Where(s => s.ProductId == p.Id)
|
|
.ToList();
|
|
return dto;
|
|
}).ToList();
|
|
|
|
// 生成对比矩阵
|
|
var comparisonMatrix = GenerateComparisonMatrix(productDtos);
|
|
|
|
return new
|
|
{
|
|
Products = productDtos,
|
|
Comparison = comparisonMatrix
|
|
};
|
|
}
|
|
|
|
private List<Dictionary<string, object>> GenerateComparisonMatrix(List<ProductDto> products)
|
|
{
|
|
var matrix = new List<Dictionary<string, object>>();
|
|
|
|
// 添加基本信息行
|
|
matrix.Add(new Dictionary<string, object> { ["指标"] = "产品名称", ["类型"] = "基本信息" });
|
|
foreach (var product in products)
|
|
{
|
|
matrix[0][$"{product.Name}"] = product.Name;
|
|
}
|
|
|
|
// 添加制造商行
|
|
matrix.Add(new Dictionary<string, object> { ["指标"] = "制造商", ["类型"] = "基本信息" });
|
|
foreach (var product in products)
|
|
{
|
|
matrix[1][$"{product.Name}"] = product.Manufacturer;
|
|
}
|
|
|
|
// 添加型号行
|
|
matrix.Add(new Dictionary<string, object> { ["指标"] = "型号", ["类型"] = "基本信息" });
|
|
foreach (var product in products)
|
|
{
|
|
matrix[2][$"{product.Name}"] = product.Model;
|
|
}
|
|
|
|
// 添加排名行
|
|
matrix.Add(new Dictionary<string, object> { ["指标"] = "当前排名", ["类型"] = "性能指标" });
|
|
foreach (var product in products)
|
|
{
|
|
matrix[3][$"{product.Name}"] = product.CurrentRank;
|
|
}
|
|
|
|
// 添加发布日期行
|
|
matrix.Add(new Dictionary<string, object> { ["指标"] = "发布日期", ["类型"] = "基本信息" });
|
|
foreach (var product in products)
|
|
{
|
|
matrix[4][$"{product.Name}"] = product.ReleaseDate.ToString("yyyy-MM-dd");
|
|
}
|
|
|
|
// 添加价格行
|
|
matrix.Add(new Dictionary<string, object> { ["指标"] = "价格", ["类型"] = "基本信息" });
|
|
foreach (var product in products)
|
|
{
|
|
matrix[5][$"{product.Name}"] = product.Price?.ToString("C") ?? "N/A";
|
|
}
|
|
|
|
// 添加性能分数行
|
|
var benchmarkTypes = products
|
|
.SelectMany(p => p.PerformanceScores)
|
|
.Select(ps => ps.BenchmarkType)
|
|
.Distinct()
|
|
.ToList();
|
|
|
|
foreach (var benchmarkType in benchmarkTypes)
|
|
{
|
|
var rowIndex = matrix.Count;
|
|
matrix.Add(new Dictionary<string, object> { ["指标"] = benchmarkType, ["类型"] = "性能指标" });
|
|
|
|
foreach (var product in products)
|
|
{
|
|
var score = product.PerformanceScores
|
|
.FirstOrDefault(ps => ps.BenchmarkType == benchmarkType)?.Score;
|
|
matrix[rowIndex][$"{product.Name}"] = score?.ToString() ?? "N/A";
|
|
}
|
|
}
|
|
|
|
// 添加规格参数行
|
|
var specNames = products
|
|
.SelectMany(p => p.Specifications)
|
|
.Select(s => s.Name)
|
|
.Distinct()
|
|
.ToList();
|
|
|
|
foreach (var specName in specNames)
|
|
{
|
|
var rowIndex = matrix.Count;
|
|
matrix.Add(new Dictionary<string, object> { ["指标"] = specName, ["类型"] = "规格参数" });
|
|
|
|
foreach (var product in products)
|
|
{
|
|
var specValue = product.Specifications
|
|
.FirstOrDefault(s => s.Name == specName)?.Value;
|
|
matrix[rowIndex][$"{product.Name}"] = specValue ?? "N/A";
|
|
}
|
|
}
|
|
|
|
// 标记最优和最差值
|
|
MarkBestAndWorstValues(matrix, products);
|
|
|
|
return matrix;
|
|
}
|
|
|
|
private void MarkBestAndWorstValues(List<Dictionary<string, object>> matrix, List<ProductDto> products)
|
|
{
|
|
// 对于排名,越小越好
|
|
var rankRow = matrix.FirstOrDefault(m => m["指标"].ToString() == "当前排名");
|
|
if (rankRow != null)
|
|
{
|
|
var ranks = products.Select(p => p.CurrentRank).ToList();
|
|
var minRank = ranks.Min();
|
|
var maxRank = ranks.Max();
|
|
|
|
foreach (var product in products)
|
|
{
|
|
var rank = product.CurrentRank;
|
|
if (rank == minRank)
|
|
{
|
|
rankRow[$"{product.Name}_isBest"] = true;
|
|
}
|
|
else if (rank == maxRank)
|
|
{
|
|
rankRow[$"{product.Name}_isWorst"] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 对于价格,越小越好
|
|
var priceRow = matrix.FirstOrDefault(m => m["指标"].ToString() == "价格");
|
|
if (priceRow != null)
|
|
{
|
|
var prices = products.Where(p => p.Price.HasValue).Select(p => p.Price!.Value).ToList();
|
|
if (prices.Any())
|
|
{
|
|
var minPrice = prices.Min();
|
|
var maxPrice = prices.Max();
|
|
|
|
foreach (var product in products)
|
|
{
|
|
if (product.Price.HasValue)
|
|
{
|
|
if (product.Price == minPrice)
|
|
{
|
|
priceRow[$"{product.Name}_isBest"] = true;
|
|
}
|
|
else if (product.Price == maxPrice)
|
|
{
|
|
priceRow[$"{product.Name}_isWorst"] = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 对于性能分数,越大越好
|
|
var performanceRows = matrix.Where(m => m["类型"].ToString() == "性能指标" &&
|
|
m["指标"].ToString() != "当前排名").ToList();
|
|
|
|
foreach (var row in performanceRows)
|
|
{
|
|
var benchmarkType = row["指标"].ToString();
|
|
var scores = new List<decimal?>();
|
|
|
|
foreach (var product in products)
|
|
{
|
|
var scoreStr = row[$"{product.Name}"]?.ToString();
|
|
if (decimal.TryParse(scoreStr, out var score))
|
|
{
|
|
scores.Add(score);
|
|
}
|
|
else
|
|
{
|
|
scores.Add(null);
|
|
}
|
|
}
|
|
|
|
var validScores = scores.Where(s => s.HasValue).Select(s => s!.Value).ToList();
|
|
if (validScores.Any())
|
|
{
|
|
var maxScore = validScores.Max();
|
|
var minScore = validScores.Min();
|
|
|
|
for (int i = 0; i < products.Count; i++)
|
|
{
|
|
if (scores[i].HasValue)
|
|
{
|
|
if (scores[i] == maxScore)
|
|
{
|
|
row[$"{products[i].Name}_isBest"] = true;
|
|
}
|
|
else if (scores[i] == minScore)
|
|
{
|
|
row[$"{products[i].Name}_isWorst"] = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |