This commit is contained in:
2025-11-03 17:03:57 +08:00
commit 7a04b85667
16804 changed files with 2492292 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
using AutoMapper;
using HardwarePerformance.Models;
using HardwarePerformance.Models.DTOs;
namespace HardwarePerformance
{
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Category, CategoryDto>();
CreateMap<Product, ProductDto>()
.ForMember(dest => dest.PerformanceScores, opt => opt.Ignore())
.ForMember(dest => dest.Specifications, opt => opt.Ignore());
CreateMap<Product, ProductListDto>();
}
}
}

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,9 @@
namespace HardwarePerformance.Models.DTOs
{
public class CategoryDto
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
}
}

View File

@@ -0,0 +1,11 @@
namespace HardwarePerformance.Models.DTOs
{
public class PagedResultDto<T>
{
public List<T> Items { get; set; } = new();
public int Total { get; set; }
public int CurrentPage { get; set; }
public int PageSize { get; set; }
public int TotalPages { get; set; }
}
}

View File

@@ -0,0 +1,20 @@
using System.Collections.Generic;
namespace HardwarePerformance.Models.DTOs
{
public class ProductDto
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Model { get; set; } = string.Empty;
public string Manufacturer { get; set; } = string.Empty;
public int CategoryId { get; set; }
public int CurrentRank { get; set; }
public DateTime ReleaseDate { get; set; }
public decimal? Price { get; set; }
public int? PerformanceScore { get; set; }
public CategoryDto? Category { get; set; }
public List<PerformanceScore> PerformanceScores { get; set; } = new();
public List<Specification> Specifications { get; set; } = new();
}
}

View File

@@ -0,0 +1,15 @@
namespace HardwarePerformance.Models.DTOs
{
public class ProductListDto
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Model { get; set; } = string.Empty;
public string Manufacturer { get; set; } = string.Empty;
public int CategoryId { get; set; }
public int CurrentRank { get; set; }
public DateTime ReleaseDate { get; set; }
public decimal? Price { get; set; }
public int? PerformanceScore { get; set; }
}
}

184
MinimalAPI/Program.cs Normal file
View File

@@ -0,0 +1,184 @@
using System.IO.Compression;
using System.Text.Json.Serialization;
namespace MinimalAPI
{
// 定义数据模型
record Category(int Id, string Name, string Description);
record Product(int Id, string Name, string Model, string Manufacturer, int CategoryId, int CurrentRank, DateTime ReleaseDate, decimal? Price);
record ApiResponse<T>(bool Success, T? Data, string? Message = null);
record PagedResponse<T>(List<T> Items, int TotalCount, int PageNumber, int PageSize, int TotalPages);
record ComparisonRequest(List<int> ProductIds);
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// 配置响应压缩
builder.Services.AddResponseCompression(options =>
{
options.EnableForHttps = true;
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[]
{
"application/json",
"application/javascript",
"text/css",
"text/html",
"text/plain",
"text/xml"
});
});
builder.Services.Configure<BrotliCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.Fastest;
});
builder.Services.Configure<GzipCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.Fastest;
});
// 配置JSON序列化选项
builder.Services.Configure<Microsoft.AspNetCore.Http.Json.JsonOptions>(options =>
{
options.SerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase;
options.SerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
// 配置CORS
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll", policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
// 注册服务
builder.Services.AddScoped<ICategoryService, CategoryService>();
builder.Services.AddScoped<IProductService, ProductService>();
builder.Services.AddScoped<IComparisonService, ComparisonService>();
var app = builder.Build();
// 添加响应压缩中间件
app.UseResponseCompression();
// 使用CORS
app.UseCors("AllowAll");
// 模拟数据
var categories = new List<Category>
{
new(1, "手机CPU", "移动设备处理器"),
new(2, "手机GPU", "移动设备图形处理器"),
new(3, "电脑CPU", "桌面和笔记本处理器"),
new(4, "电脑GPU", "桌面和笔记本图形处理器")
};
var products = new List<Product>
{
new(1, "Apple A17 Pro", "A17 Pro", "Apple", 1, 1, new DateTime(2023, 9, 12), null),
new(2, "Snapdragon 8 Gen 3", "SM8650-AB", "Qualcomm", 1, 2, new DateTime(2023, 10, 24), null),
new(3, "Intel Core i9-13900K", "Core i9-13900K", "Intel", 3, 1, new DateTime(2022, 10, 20), 589.99m),
new(4, "AMD Ryzen 9 7950X", "Ryzen 9 7950X", "AMD", 3, 2, new DateTime(2022, 9, 27), 699.99m),
new(5, "NVIDIA GeForce RTX 4090", "RTX 4090", "NVIDIA", 4, 1, new DateTime(2022, 10, 12), 1599.99m),
new(6, "AMD Radeon RX 7900 XTX", "RX 7900 XTX", "AMD", 4, 2, new DateTime(2022, 12, 3), 999.99m)
};
// API端点
// 类别相关
app.MapGet("/api/categories", async (ICategoryService categoryService) =>
{
var categories = await categoryService.GetAllCategoriesAsync();
return Results.Ok(new ApiResponse<List<CategoryDto>>(true, categories));
});
app.MapGet("/api/categories/{id}", async (int id, ICategoryService categoryService) =>
{
var category = await categoryService.GetCategoryByIdAsync(id);
if (category == null)
{
return Results.NotFound(new ApiResponse<object>(false, null, "类别不存在"));
}
return Results.Ok(new ApiResponse<CategoryDto>(true, category));
});
// 产品API
app.MapGet("/api/products", async (int? categoryId, int page = 1, int pageSize = 20, string sortBy = "CurrentRank", string sortOrder = "asc", IProductService productService) =>
{
if (!categoryId.HasValue)
{
return Results.BadRequest(new ApiResponse<object>(false, null, "类别ID是必需的"));
}
var pagedResult = await productService.GetProductsByCategoryAsync(categoryId.Value, page, pageSize, sortBy, sortOrder);
return Results.Ok(new ApiResponse<PagedResultDto<ProductListDto>>(true, pagedResult));
});
app.MapGet("/api/products/{id}", async (int id, IProductService productService) =>
{
var product = await productService.GetProductByIdAsync(id);
if (product == null)
{
return Results.NotFound(new ApiResponse<object>(false, null, "产品不存在"));
}
return Results.Ok(new ApiResponse<ProductDto>(true, product));
});
app.MapGet("/api/products/search", async (string q, int? categoryId, string? manufacturer, decimal? minScore, decimal? maxScore, int page = 1, int pageSize = 20, IProductService productService) =>
{
if (string.IsNullOrWhiteSpace(q))
{
return Results.BadRequest(new ApiResponse<object>(false, null, "搜索关键词不能为空"));
}
var pagedResult = await productService.SearchProductsAsync(q, categoryId, manufacturer, minScore, maxScore, page, pageSize);
return Results.Ok(new ApiResponse<PagedResultDto<ProductListDto>>(true, pagedResult));
});
app.MapGet("/api/products/filter", async (int categoryId, string? manufacturer, decimal? minScore, decimal? maxScore, int? year, int page = 1, int pageSize = 20, IProductService productService) =>
{
var pagedResult = await productService.FilterProductsAsync(categoryId, manufacturer, minScore, maxScore, year, page, pageSize);
return Results.Ok(new ApiResponse<PagedResultDto<ProductListDto>>(true, pagedResult));
});
// 产品对比
app.MapPost("/api/comparison", async (ComparisonRequest request, IComparisonService comparisonService) =>
{
// 验证请求
if (request.ProductIds == null || request.ProductIds.Count < 2 || request.ProductIds.Count > 4)
{
return Results.BadRequest(new ApiResponse<object>(false, null, "产品ID数量必须在2到4之间"));
}
var comparisonData = await comparisonService.CompareProductsAsync(request.ProductIds);
if (comparisonData == null)
{
return Results.NotFound(new ApiResponse<object>(false, null, "无法获取产品对比数据"));
}
return Results.Ok(new ApiResponse<object>(true, comparisonData));
});
// 状态检查端点
app.MapGet("/api/status", () => new
{
Status = "Running",
Message = "API服务正常运行",
Timestamp = DateTime.Now,
Version = "1.0.0"
});
app.Run();
}
}
}

View File

@@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5172",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7055;http://localhost:5172",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore;
using HardwarePerformance.Data;
using HardwarePerformance.Models;
namespace HardwarePerformance.Repositories
{
public class CategoryRepository : Repository<Category>, ICategoryRepository
{
public CategoryRepository(AppDbContext context) : base(context)
{
}
public async Task<Category?> GetByNameAsync(string name)
{
return await _dbSet.FirstOrDefaultAsync(c => c.Name == name);
}
public async Task<bool> ExistsAsync(int id)
{
return await _dbSet.AnyAsync(c => c.Id == id);
}
public async Task<bool> NameExistsAsync(string name)
{
return await _dbSet.AnyAsync(c => c.Name == name);
}
}
}

View File

@@ -0,0 +1,11 @@
using HardwarePerformance.Models;
namespace HardwarePerformance.Repositories
{
public interface ICategoryRepository : IRepository<Category>
{
Task<Category?> GetByNameAsync(string name);
Task<bool> ExistsAsync(int id);
Task<bool> NameExistsAsync(string name);
}
}

View File

@@ -0,0 +1,18 @@
using HardwarePerformance.Models;
namespace HardwarePerformance.Repositories
{
public interface IProductRepository : IRepository<Product>
{
Task<IEnumerable<Product>> GetByCategoryAsync(int categoryId);
Task<IEnumerable<Product>> GetByCategoryAsync(int categoryId, int page, int pageSize, string sortBy = "CurrentRank", string sortOrder = "asc");
Task<IEnumerable<Product>> SearchAsync(string query);
Task<IEnumerable<Product>> SearchAsync(string query, int? categoryId = null, string? manufacturer = null, int? minScore = null, int? maxScore = null, int page = 1, int pageSize = 20);
Task<IEnumerable<Product>> FilterAsync(int? categoryId, string? manufacturer, int? minScore, int? maxScore, int? year);
Task<IEnumerable<Product>> FilterAsync(int? categoryId, string? manufacturer, int? minScore, int? maxScore, int? year, int page, int pageSize, string sortBy = "CurrentRank", string sortOrder = "asc");
Task<int> CountAsync(int? categoryId = null);
Task<int> CountSearchResultsAsync(string query, int? categoryId = null, string? manufacturer = null, int? minScore = null, int? maxScore = null);
Task<int> CountFilterResultsAsync(int? categoryId, string? manufacturer, int? minScore, int? maxScore, int? year);
Task<Category?> GetCategoryByProductIdAsync(int productId);
}
}

View File

@@ -0,0 +1,16 @@
using System.Linq.Expressions;
using HardwarePerformance.Models;
namespace HardwarePerformance.Repositories
{
public interface IRepository<T> where T : class
{
Task<T?> GetByIdAsync(int id);
Task<IEnumerable<T>> GetAllAsync();
Task<IEnumerable<T>> FindAsync(Expression<Func<T, bool>> predicate);
Task<T> AddAsync(T entity);
Task UpdateAsync(T entity);
Task DeleteAsync(T entity);
Task<int> CountAsync(Expression<Func<T, bool>>? predicate = null);
}
}

View File

@@ -0,0 +1,265 @@
using Microsoft.EntityFrameworkCore;
using HardwarePerformance.Data;
using HardwarePerformance.Models;
namespace HardwarePerformance.Repositories
{
public class ProductRepository : Repository<Product>, IProductRepository
{
public ProductRepository(AppDbContext context) : base(context)
{
}
public async Task<IEnumerable<Product>> GetByCategoryAsync(int categoryId)
{
return await _dbSet
.Where(p => p.CategoryId == categoryId)
.OrderBy(p => p.CurrentRank)
.ToListAsync();
}
public async Task<IEnumerable<Product>> GetByCategoryAsync(int categoryId, int page, int pageSize, string sortBy = "CurrentRank", string sortOrder = "asc")
{
var query = _dbSet.Where(p => p.CategoryId == categoryId);
// 排序
query = sortBy.ToLower() switch
{
"name" => sortOrder.ToLower() == "desc" ? query.OrderByDescending(p => p.Name) : query.OrderBy(p => p.Name),
"manufacturer" => sortOrder.ToLower() == "desc" ? query.OrderByDescending(p => p.Manufacturer) : query.OrderBy(p => p.Manufacturer),
"releasedate" => sortOrder.ToLower() == "desc" ? query.OrderByDescending(p => p.ReleaseDate) : query.OrderBy(p => p.ReleaseDate),
"price" => sortOrder.ToLower() == "desc" ? query.OrderByDescending(p => p.Price) : query.OrderBy(p => p.Price),
_ => sortOrder.ToLower() == "desc" ? query.OrderByDescending(p => p.CurrentRank) : query.OrderBy(p => p.CurrentRank)
};
return await query
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
}
public async Task<IEnumerable<Product>> SearchAsync(string query)
{
return await _dbSet
.Where(p =>
p.Name.Contains(query) ||
p.Model.Contains(query) ||
p.Manufacturer.Contains(query))
.ToListAsync();
}
public async Task<IEnumerable<Product>> SearchAsync(string query, int? categoryId = null, string? manufacturer = null, int? minScore = null, int? maxScore = null, int page = 1, int pageSize = 20)
{
var queryable = _dbSet.AsQueryable();
if (categoryId.HasValue)
{
queryable = queryable.Where(p => p.CategoryId == categoryId.Value);
}
if (!string.IsNullOrEmpty(manufacturer))
{
queryable = queryable.Where(p => p.Manufacturer == manufacturer);
}
if (minScore.HasValue)
{
// 使用排名计算性能分数100 - 排名)
queryable = queryable.Where(p => (100 - p.CurrentRank) >= minScore.Value);
}
if (maxScore.HasValue)
{
// 使用排名计算性能分数100 - 排名)
queryable = queryable.Where(p => (100 - p.CurrentRank) <= maxScore.Value);
}
if (!string.IsNullOrEmpty(query))
{
queryable = queryable.Where(p =>
p.Name.Contains(query) ||
p.Model.Contains(query) ||
p.Manufacturer.Contains(query));
}
return await queryable
.OrderBy(p => p.CurrentRank)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
}
public async Task<IEnumerable<Product>> FilterAsync(int? categoryId, string? manufacturer, int? minScore, int? maxScore, int? year)
{
var query = _dbSet.AsQueryable();
if (categoryId.HasValue)
{
query = query.Where(p => p.CategoryId == categoryId.Value);
}
if (!string.IsNullOrEmpty(manufacturer))
{
query = query.Where(p => p.Manufacturer == manufacturer);
}
if (minScore.HasValue)
{
// 使用排名计算性能分数100 - 排名)
query = query.Where(p => (100 - p.CurrentRank) >= minScore.Value);
}
if (maxScore.HasValue)
{
// 使用排名计算性能分数100 - 排名)
query = query.Where(p => (100 - p.CurrentRank) <= maxScore.Value);
}
if (year.HasValue)
{
query = query.Where(p => p.ReleaseDate.Year == year.Value);
}
return await query.ToListAsync();
}
public async Task<IEnumerable<Product>> FilterAsync(int? categoryId, string? manufacturer, int? minScore, int? maxScore, int? year, int page, int pageSize, string sortBy = "CurrentRank", string sortOrder = "asc")
{
var query = _dbSet.AsQueryable();
if (categoryId.HasValue)
{
query = query.Where(p => p.CategoryId == categoryId.Value);
}
if (!string.IsNullOrEmpty(manufacturer))
{
query = query.Where(p => p.Manufacturer == manufacturer);
}
if (minScore.HasValue)
{
// 使用排名计算性能分数100 - 排名)
query = query.Where(p => (100 - p.CurrentRank) >= minScore.Value);
}
if (maxScore.HasValue)
{
// 使用排名计算性能分数100 - 排名)
query = query.Where(p => (100 - p.CurrentRank) <= maxScore.Value);
}
if (year.HasValue)
{
query = query.Where(p => p.ReleaseDate.Year == year.Value);
}
// 排序
query = sortBy.ToLower() switch
{
"name" => sortOrder.ToLower() == "desc" ? query.OrderByDescending(p => p.Name) : query.OrderBy(p => p.Name),
"manufacturer" => sortOrder.ToLower() == "desc" ? query.OrderByDescending(p => p.Manufacturer) : query.OrderBy(p => p.Manufacturer),
"releasedate" => sortOrder.ToLower() == "desc" ? query.OrderByDescending(p => p.ReleaseDate) : query.OrderBy(p => p.ReleaseDate),
"price" => sortOrder.ToLower() == "desc" ? query.OrderByDescending(p => p.Price) : query.OrderBy(p => p.Price),
_ => sortOrder.ToLower() == "desc" ? query.OrderByDescending(p => p.CurrentRank) : query.OrderBy(p => p.CurrentRank)
};
return await query
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
}
public async Task<int> CountAsync(int? categoryId = null)
{
var query = _dbSet.AsQueryable();
if (categoryId.HasValue)
{
query = query.Where(p => p.CategoryId == categoryId.Value);
}
return await query.CountAsync();
}
public async Task<int> CountSearchResultsAsync(string query, int? categoryId = null, string? manufacturer = null, int? minScore = null, int? maxScore = null)
{
var queryable = _dbSet.AsQueryable();
if (categoryId.HasValue)
{
queryable = queryable.Where(p => p.CategoryId == categoryId.Value);
}
if (!string.IsNullOrEmpty(manufacturer))
{
queryable = queryable.Where(p => p.Manufacturer == manufacturer);
}
if (minScore.HasValue)
{
// 使用排名计算性能分数100 - 排名)
queryable = queryable.Where(p => (100 - p.CurrentRank) >= minScore.Value);
}
if (maxScore.HasValue)
{
// 使用排名计算性能分数100 - 排名)
queryable = queryable.Where(p => (100 - p.CurrentRank) <= maxScore.Value);
}
if (!string.IsNullOrEmpty(query))
{
queryable = queryable.Where(p =>
p.Name.Contains(query) ||
p.Model.Contains(query) ||
p.Manufacturer.Contains(query));
}
return await queryable.CountAsync();
}
public async Task<int> CountFilterResultsAsync(int? categoryId, string? manufacturer, int? minScore, int? maxScore, int? year)
{
var query = _dbSet.AsQueryable();
if (categoryId.HasValue)
{
query = query.Where(p => p.CategoryId == categoryId.Value);
}
if (!string.IsNullOrEmpty(manufacturer))
{
query = query.Where(p => p.Manufacturer == manufacturer);
}
if (minScore.HasValue)
{
// 使用排名计算性能分数100 - 排名)
query = query.Where(p => (100 - p.CurrentRank) >= minScore.Value);
}
if (maxScore.HasValue)
{
// 使用排名计算性能分数100 - 排名)
query = query.Where(p => (100 - p.CurrentRank) <= maxScore.Value);
}
if (year.HasValue)
{
query = query.Where(p => p.ReleaseDate.Year == year.Value);
}
return await query.CountAsync();
}
public async Task<Category?> GetCategoryByProductIdAsync(int productId)
{
var product = await _dbSet
.Include(p => p.Category)
.FirstOrDefaultAsync(p => p.Id == productId);
return product?.Category;
}
}
}

View File

@@ -0,0 +1,60 @@
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using HardwarePerformance.Data;
using HardwarePerformance.Models;
namespace HardwarePerformance.Repositories
{
public class Repository<T> : IRepository<T> where T : class
{
protected readonly AppDbContext _context;
protected readonly DbSet<T> _dbSet;
public Repository(AppDbContext context)
{
_context = context;
_dbSet = context.Set<T>();
}
public async Task<T?> GetByIdAsync(int id)
{
return await _dbSet.FindAsync(id);
}
public async Task<IEnumerable<T>> GetAllAsync()
{
return await _dbSet.ToListAsync();
}
public async Task<IEnumerable<T>> FindAsync(Expression<Func<T, bool>> predicate)
{
return await _dbSet.Where(predicate).ToListAsync();
}
public async Task<T> AddAsync(T entity)
{
await _dbSet.AddAsync(entity);
await _context.SaveChangesAsync();
return entity;
}
public async Task UpdateAsync(T entity)
{
_dbSet.Update(entity);
await _context.SaveChangesAsync();
}
public async Task DeleteAsync(T entity)
{
_dbSet.Remove(entity);
await _context.SaveChangesAsync();
}
public async Task<int> CountAsync(Expression<Func<T, bool>>? predicate = null)
{
if (predicate == null)
return await _dbSet.CountAsync();
return await _dbSet.CountAsync(predicate);
}
}
}

View File

@@ -0,0 +1,30 @@
using AutoMapper;
using HardwarePerformance.Models.DTOs;
using HardwarePerformance.Repositories;
namespace HardwarePerformance.Services
{
public class CategoryService : ICategoryService
{
private readonly ICategoryRepository _categoryRepository;
private readonly IMapper _mapper;
public CategoryService(ICategoryRepository categoryRepository, IMapper mapper)
{
_categoryRepository = categoryRepository;
_mapper = mapper;
}
public async Task<IEnumerable<CategoryDto>> GetAllCategoriesAsync()
{
var categories = await _categoryRepository.GetAllAsync();
return _mapper.Map<IEnumerable<CategoryDto>>(categories);
}
public async Task<CategoryDto?> GetCategoryByIdAsync(int id)
{
var category = await _categoryRepository.GetByIdAsync(id);
return category != null ? _mapper.Map<CategoryDto>(category) : null;
}
}
}

View File

@@ -0,0 +1,271 @@
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;
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,10 @@
using HardwarePerformance.Models.DTOs;
namespace HardwarePerformance.Services
{
public interface ICategoryService
{
Task<IEnumerable<CategoryDto>> GetAllCategoriesAsync();
Task<CategoryDto?> GetCategoryByIdAsync(int id);
}
}

View File

@@ -0,0 +1,10 @@
using System.Collections.Generic;
using System.Threading.Tasks;
namespace MinimalAPI.Services
{
public interface IComparisonService
{
Task<object> CompareProductsAsync(List<int> productIds);
}
}

View File

@@ -0,0 +1,12 @@
using HardwarePerformance.Models.DTOs;
namespace HardwarePerformance.Services
{
public interface IProductService
{
Task<PagedResultDto<ProductListDto>> GetProductsByCategoryAsync(int categoryId, int page = 1, int pageSize = 20, string sortBy = "CurrentRank", string order = "asc");
Task<ProductDto?> GetProductByIdAsync(int id);
Task<PagedResultDto<ProductListDto>> SearchProductsAsync(string query, int? categoryId = null, string? manufacturer = null, int? minScore = null, int? maxScore = null, int page = 1, int pageSize = 20);
Task<PagedResultDto<ProductListDto>> FilterProductsAsync(int categoryId, string? manufacturer = null, int? minScore = null, int? maxScore = null, int? releaseYear = null, int page = 1, int pageSize = 20, string sortBy = "CurrentRank", string order = "asc");
}
}

View File

@@ -0,0 +1,91 @@
using AutoMapper;
using HardwarePerformance.Models.DTOs;
using HardwarePerformance.Repositories;
namespace HardwarePerformance.Services
{
public class ProductService : IProductService
{
private readonly IProductRepository _productRepository;
private readonly IMapper _mapper;
public ProductService(IProductRepository productRepository, IMapper mapper)
{
_productRepository = productRepository;
_mapper = mapper;
}
public async Task<PagedResultDto<ProductListDto>> GetProductsByCategoryAsync(int categoryId, int page = 1, int pageSize = 20, string sortBy = "CurrentRank", string order = "asc")
{
var products = await _productRepository.GetByCategoryAsync(categoryId, page, pageSize, sortBy, order);
var totalCount = await _productRepository.CountAsync(categoryId);
var productDtos = _mapper.Map<IEnumerable<ProductListDto>>(products);
return new PagedResultDto<ProductListDto>
{
Items = productDtos.ToList(),
Total = totalCount,
CurrentPage = page,
PageSize = pageSize,
TotalPages = (int)Math.Ceiling((double)totalCount / pageSize)
};
}
public async Task<ProductDto?> GetProductByIdAsync(int id)
{
var product = await _productRepository.GetByIdAsync(id);
if (product == null) return null;
var productDto = _mapper.Map<ProductDto>(product);
// 获取类别信息
var category = await _productRepository.GetCategoryByProductIdAsync(id);
if (category != null)
{
productDto.Category = new CategoryDto
{
Id = category.Id,
Name = category.Name,
Description = category.Description
};
}
return productDto;
}
public async Task<PagedResultDto<ProductListDto>> SearchProductsAsync(string query, int? categoryId = null, string? manufacturer = null, int? minScore = null, int? maxScore = null, int page = 1, int pageSize = 20)
{
var products = await _productRepository.SearchAsync(query, categoryId, manufacturer, minScore, maxScore, page, pageSize);
var totalCount = await _productRepository.CountSearchResultsAsync(query, categoryId, manufacturer, minScore, maxScore);
var productDtos = _mapper.Map<IEnumerable<ProductListDto>>(products);
return new PagedResultDto<ProductListDto>
{
Items = productDtos.ToList(),
Total = totalCount,
CurrentPage = page,
PageSize = pageSize,
TotalPages = (int)Math.Ceiling((double)totalCount / pageSize)
};
}
public async Task<PagedResultDto<ProductListDto>> FilterProductsAsync(int categoryId, string? manufacturer = null, int? minScore = null, int? maxScore = null, int? releaseYear = null, int page = 1, int pageSize = 20, string sortBy = "CurrentRank", string order = "asc")
{
var products = await _productRepository.FilterAsync(categoryId, manufacturer, minScore, maxScore, releaseYear, page, pageSize, sortBy, order);
var totalCount = await _productRepository.CountFilterResultsAsync(categoryId, manufacturer, minScore, maxScore, releaseYear);
var productDtos = _mapper.Map<IEnumerable<ProductListDto>>(products);
return new PagedResultDto<ProductListDto>
{
Items = productDtos.ToList(),
Total = totalCount,
CurrentPage = page,
PageSize = pageSize,
TotalPages = (int)Math.Ceiling((double)totalCount / pageSize)
};
}
}
}

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@@ -0,0 +1,23 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v9.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v9.0": {
"MinimalAPI/1.0.0": {
"runtime": {
"MinimalAPI.dll": {}
}
}
}
},
"libraries": {
"MinimalAPI/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,19 @@
{
"runtimeOptions": {
"tfm": "net9.0",
"frameworks": [
{
"name": "Microsoft.NETCore.App",
"version": "9.0.0"
},
{
"name": "Microsoft.AspNetCore.App",
"version": "9.0.0"
}
],
"configProperties": {
"System.GC.Server": true,
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
}
}
}

View File

@@ -0,0 +1 @@
{"Version":1,"ManifestType":"Build","Endpoints":[]}

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0")]

View File

@@ -0,0 +1,22 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("MinimalAPI")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
[assembly: System.Reflection.AssemblyProductAttribute("MinimalAPI")]
[assembly: System.Reflection.AssemblyTitleAttribute("MinimalAPI")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// 由 MSBuild WriteCodeFragment 类生成。

View File

@@ -0,0 +1 @@
d440d87b19ec785d73e3e23306ab9680f7c4890517e977a1c254363c4f9347af

View File

@@ -0,0 +1,21 @@
is_global = true
build_property.TargetFramework = net9.0
build_property.TargetPlatformMinVersion =
build_property.UsingMicrosoftNETSdkWeb = true
build_property.ProjectTypeGuids =
build_property.InvariantGlobalization =
build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules =
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = MinimalAPI
build_property.RootNamespace = MinimalAPI
build_property.ProjectDir = C:\work\电脑硬件-01\MinimalAPI\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.RazorLangVersion = 9.0
build_property.SupportLocalizedComponentNames =
build_property.GenerateRazorMetadataSourceChecksumAttributes =
build_property.MSBuildProjectDirectory = C:\work\电脑硬件-01\MinimalAPI
build_property._RazorSourceGeneratorDebug =
build_property.EffectiveAnalysisLevelStyle = 9.0
build_property.EnableCodeStyleSeverity =

View File

@@ -0,0 +1,17 @@
// <auto-generated/>
global using global::Microsoft.AspNetCore.Builder;
global using global::Microsoft.AspNetCore.Hosting;
global using global::Microsoft.AspNetCore.Http;
global using global::Microsoft.AspNetCore.Routing;
global using global::Microsoft.Extensions.Configuration;
global using global::Microsoft.Extensions.DependencyInjection;
global using global::Microsoft.Extensions.Hosting;
global using global::Microsoft.Extensions.Logging;
global using global::System;
global using global::System.Collections.Generic;
global using global::System.IO;
global using global::System.Linq;
global using global::System.Net.Http;
global using global::System.Net.Http.Json;
global using global::System.Threading;
global using global::System.Threading.Tasks;

Binary file not shown.

View File

@@ -0,0 +1 @@
05c277f9ef6d1c96b7c3a0662bb97967ee23e63c93d8aa1cd4aec40fc1c9febe

View File

@@ -0,0 +1,27 @@
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\rpswa.dswa.cache.json
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\MinimalAPI.GeneratedMSBuildEditorConfig.editorconfig
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\MinimalAPI.AssemblyInfoInputs.cache
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\MinimalAPI.AssemblyInfo.cs
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\MinimalAPI.csproj.CoreCompileInputs.cache
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\MinimalAPI.MvcApplicationPartsAssemblyInfo.cache
C:\work\电脑硬件-01\MinimalAPI\bin\Debug\net9.0\appsettings.Development.json
C:\work\电脑硬件-01\MinimalAPI\bin\Debug\net9.0\appsettings.json
C:\work\电脑硬件-01\MinimalAPI\bin\Debug\net9.0\MinimalAPI.staticwebassets.endpoints.json
C:\work\电脑硬件-01\MinimalAPI\bin\Debug\net9.0\MinimalAPI.exe
C:\work\电脑硬件-01\MinimalAPI\bin\Debug\net9.0\MinimalAPI.deps.json
C:\work\电脑硬件-01\MinimalAPI\bin\Debug\net9.0\MinimalAPI.runtimeconfig.json
C:\work\电脑硬件-01\MinimalAPI\bin\Debug\net9.0\MinimalAPI.dll
C:\work\电脑硬件-01\MinimalAPI\bin\Debug\net9.0\MinimalAPI.pdb
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\rjimswa.dswa.cache.json
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\rjsmrazor.dswa.cache.json
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\rjsmcshtml.dswa.cache.json
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\scopedcss\bundle\MinimalAPI.styles.css
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\staticwebassets.build.json
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\staticwebassets.build.json.cache
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\staticwebassets.development.json
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\staticwebassets.build.endpoints.json
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\MinimalAPI.dll
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\refint\MinimalAPI.dll
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\MinimalAPI.pdb
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\MinimalAPI.genruntimeconfig.cache
C:\work\电脑硬件-01\MinimalAPI\obj\Debug\net9.0\ref\MinimalAPI.dll

Binary file not shown.

View File

@@ -0,0 +1 @@
2cc508c4c984e00de0cee28ea5f00a982100be8dad563e9011ff5619c65193f1

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
{"GlobalPropertiesHash":"UvHx1BUBnfpFc6gxIpp/8mxp/Pr5ugj++Q4ag8rCqAY=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["vICfSWyJTl7Llwoo5pZeHmuInfb\u002BPDuiEXf67e03aVY=","HGCAjAUzY86/cTTfeLk8LuqAnP1lIVdvBKQP\u002BJ23JAc=","pXPB2q0SLSiqgQ6QWxaK7/r8KBQLxQCCriy2hCwae1A=","eZ0avPpvDZzkkkg3Y40\u002B9/FcOts1TlMSAvHEIAFbU8Q="],"CachedAssets":{},"CachedCopyCandidates":{}}

View File

@@ -0,0 +1 @@
{"GlobalPropertiesHash":"N05q42TiGbCpQThCMeppx1cqHYMYPr+MKOVECH+LM5o=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["vICfSWyJTl7Llwoo5pZeHmuInfb\u002BPDuiEXf67e03aVY=","HGCAjAUzY86/cTTfeLk8LuqAnP1lIVdvBKQP\u002BJ23JAc=","pXPB2q0SLSiqgQ6QWxaK7/r8KBQLxQCCriy2hCwae1A=","eZ0avPpvDZzkkkg3Y40\u002B9/FcOts1TlMSAvHEIAFbU8Q="],"CachedAssets":{},"CachedCopyCandidates":{}}

View File

@@ -0,0 +1 @@
{"GlobalPropertiesHash":"Qscza4zuOZL6qExaAaOGJZbKXeiSjSngMQ6k1ALDEr8=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["vICfSWyJTl7Llwoo5pZeHmuInfb\u002BPDuiEXf67e03aVY=","HGCAjAUzY86/cTTfeLk8LuqAnP1lIVdvBKQP\u002BJ23JAc="],"CachedAssets":{},"CachedCopyCandidates":{}}

View File

@@ -0,0 +1 @@
{"Version":1,"ManifestType":"Build","Endpoints":[]}

View File

@@ -0,0 +1 @@
{"Version":1,"Hash":"JkTLtN583la2vWjETk7JpCURqkzL9J5tTWuu+nxCKow=","Source":"MinimalAPI","BasePath":"_content/MinimalAPI","Mode":"Default","ManifestType":"Build","ReferencedProjectsConfiguration":[],"DiscoveryPatterns":[],"Assets":[],"Endpoints":[]}

View File

@@ -0,0 +1 @@
JkTLtN583la2vWjETk7JpCURqkzL9J5tTWuu+nxCKow=

View File

@@ -0,0 +1,86 @@
{
"format": 1,
"restore": {
"C:\\work\\电脑硬件-01\\MinimalAPI\\MinimalAPI.csproj": {}
},
"projects": {
"C:\\work\\电脑硬件-01\\MinimalAPI\\MinimalAPI.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "C:\\work\\电脑硬件-01\\MinimalAPI\\MinimalAPI.csproj",
"projectName": "MinimalAPI",
"projectPath": "C:\\work\\电脑硬件-01\\MinimalAPI\\MinimalAPI.csproj",
"packagesPath": "C:\\Users\\代\\.nuget\\packages\\",
"outputPath": "C:\\work\\电脑硬件-01\\MinimalAPI\\obj\\",
"projectStyle": "PackageReference",
"fallbackFolders": [
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
],
"configFilePaths": [
"C:\\Users\\代\\AppData\\Roaming\\NuGet\\NuGet.Config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
],
"originalTargetFrameworks": [
"net9.0"
],
"sources": {
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
"https://api.nuget.org/v3/index.json": {},
"https://nuget.cdn.azure.cn/v3/index.json": {},
"https://packages.chinacloudapi.cn/v3/index.json": {},
"https://packages.microsoft.com/dotnet": {},
"https://www.nuget.org/api/v2/": {}
},
"frameworks": {
"net9.0": {
"targetAlias": "net9.0",
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.300"
},
"frameworks": {
"net9.0": {
"targetAlias": "net9.0",
"dependencies": {
"Microsoft.AspNetCore.ResponseCompression": {
"target": "Package",
"version": "[2.2.0, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"frameworkReferences": {
"Microsoft.AspNetCore.App": {
"privateAssets": "none"
},
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.304/PortableRuntimeIdentifierGraph.json"
}
}
}
}
}

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\代\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.14.0</NuGetToolVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="C:\Users\代\.nuget\packages\" />
<SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />

View File

@@ -0,0 +1,102 @@
{
"version": 3,
"targets": {
"net9.0": {}
},
"libraries": {},
"projectFileDependencyGroups": {
"net9.0": [
"Microsoft.AspNetCore.ResponseCompression >= 2.2.0"
]
},
"packageFolders": {
"C:\\Users\\代\\.nuget\\packages\\": {},
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {}
},
"project": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "C:\\work\\电脑硬件-01\\MinimalAPI\\MinimalAPI.csproj",
"projectName": "MinimalAPI",
"projectPath": "C:\\work\\电脑硬件-01\\MinimalAPI\\MinimalAPI.csproj",
"packagesPath": "C:\\Users\\代\\.nuget\\packages\\",
"outputPath": "C:\\work\\电脑硬件-01\\MinimalAPI\\obj\\",
"projectStyle": "PackageReference",
"fallbackFolders": [
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
],
"configFilePaths": [
"C:\\Users\\代\\AppData\\Roaming\\NuGet\\NuGet.Config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
],
"originalTargetFrameworks": [
"net9.0"
],
"sources": {
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
"https://api.nuget.org/v3/index.json": {},
"https://nuget.cdn.azure.cn/v3/index.json": {},
"https://packages.chinacloudapi.cn/v3/index.json": {},
"https://packages.microsoft.com/dotnet": {},
"https://www.nuget.org/api/v2/": {}
},
"frameworks": {
"net9.0": {
"targetAlias": "net9.0",
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.300"
},
"frameworks": {
"net9.0": {
"targetAlias": "net9.0",
"dependencies": {
"Microsoft.AspNetCore.ResponseCompression": {
"target": "Package",
"version": "[2.2.0, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"frameworkReferences": {
"Microsoft.AspNetCore.App": {
"privateAssets": "none"
},
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.304/PortableRuntimeIdentifierGraph.json"
}
}
},
"logs": [
{
"code": "NU1301",
"level": "Error",
"message": "未能从远程源“https://www.nuget.org/api/v2/FindPackagesById()?id='Microsoft.AspNetCore.ResponseCompression'&semVerLevel=2.0.0”检索有关“Microsoft.AspNetCore.ResponseCompression”的信息。\r\n 不知道这样的主机。 (null:80)\r\n 不知道这样的主机。",
"libraryId": "Microsoft.AspNetCore.ResponseCompression"
}
]
}

View File

@@ -0,0 +1,18 @@
{
"version": 2,
"dgSpecHash": "ionCG+ayp8g=",
"success": false,
"projectFilePath": "C:\\work\\电脑硬件-01\\MinimalAPI\\MinimalAPI.csproj",
"expectedPackageFiles": [],
"logs": [
{
"code": "NU1301",
"level": "Error",
"message": "未能从远程源“https://www.nuget.org/api/v2/FindPackagesById()?id='Microsoft.AspNetCore.ResponseCompression'&semVerLevel=2.0.0”检索有关“Microsoft.AspNetCore.ResponseCompression”的信息。\r\n 不知道这样的主机。 (null:80)\r\n 不知道这样的主机。",
"projectPath": "C:\\work\\电脑硬件-01\\MinimalAPI\\MinimalAPI.csproj",
"filePath": "C:\\work\\电脑硬件-01\\MinimalAPI\\MinimalAPI.csproj",
"libraryId": "Microsoft.AspNetCore.ResponseCompression",
"targetGraphs": []
}
]
}