252 lines
9.0 KiB
C#
252 lines
9.0 KiB
C#
|
|
using Microsoft.AspNetCore.Mvc;
|
|||
|
|
using HardwarePerformance.API.Models;
|
|||
|
|
using HardwarePerformance.Infrastructure.Services;
|
|||
|
|
|
|||
|
|
namespace HardwarePerformance.API.Controllers
|
|||
|
|
{
|
|||
|
|
[ApiController]
|
|||
|
|
[Route("api/[controller]")]
|
|||
|
|
public class ProductsController : ControllerBase
|
|||
|
|
{
|
|||
|
|
private static readonly List<Product> _products = new()
|
|||
|
|
{
|
|||
|
|
new Product
|
|||
|
|
{
|
|||
|
|
Id = 1,
|
|||
|
|
Name = "Apple A17 Pro",
|
|||
|
|
Model = "A17 Pro",
|
|||
|
|
Manufacturer = "Apple",
|
|||
|
|
CategoryId = 1,
|
|||
|
|
CurrentRank = 1,
|
|||
|
|
ReleaseDate = new DateTime(2023, 9, 12),
|
|||
|
|
Price = null
|
|||
|
|
},
|
|||
|
|
new Product
|
|||
|
|
{
|
|||
|
|
Id = 2,
|
|||
|
|
Name = "Snapdragon 8 Gen 3",
|
|||
|
|
Model = "SM8650-AB",
|
|||
|
|
Manufacturer = "Qualcomm",
|
|||
|
|
CategoryId = 1,
|
|||
|
|
CurrentRank = 2,
|
|||
|
|
ReleaseDate = new DateTime(2023, 10, 24),
|
|||
|
|
Price = null
|
|||
|
|
},
|
|||
|
|
new Product
|
|||
|
|
{
|
|||
|
|
Id = 3,
|
|||
|
|
Name = "Intel Core i9-13900K",
|
|||
|
|
Model = "Core i9-13900K",
|
|||
|
|
Manufacturer = "Intel",
|
|||
|
|
CategoryId = 3,
|
|||
|
|
CurrentRank = 1,
|
|||
|
|
ReleaseDate = new DateTime(2022, 10, 20),
|
|||
|
|
Price = 589.99m
|
|||
|
|
},
|
|||
|
|
new Product
|
|||
|
|
{
|
|||
|
|
Id = 4,
|
|||
|
|
Name = "AMD Ryzen 9 7950X",
|
|||
|
|
Model = "Ryzen 9 7950X",
|
|||
|
|
Manufacturer = "AMD",
|
|||
|
|
CategoryId = 3,
|
|||
|
|
CurrentRank = 2,
|
|||
|
|
ReleaseDate = new DateTime(2022, 9, 27),
|
|||
|
|
Price = 699.99m
|
|||
|
|
},
|
|||
|
|
new Product
|
|||
|
|
{
|
|||
|
|
Id = 5,
|
|||
|
|
Name = "NVIDIA GeForce RTX 4090",
|
|||
|
|
Model = "RTX 4090",
|
|||
|
|
Manufacturer = "NVIDIA",
|
|||
|
|
CategoryId = 4,
|
|||
|
|
CurrentRank = 1,
|
|||
|
|
ReleaseDate = new DateTime(2022, 10, 12),
|
|||
|
|
Price = 1599.99m
|
|||
|
|
},
|
|||
|
|
new Product
|
|||
|
|
{
|
|||
|
|
Id = 6,
|
|||
|
|
Name = "AMD Radeon RX 7900 XTX",
|
|||
|
|
Model = "RX 7900 XTX",
|
|||
|
|
Manufacturer = "AMD",
|
|||
|
|
CategoryId = 4,
|
|||
|
|
CurrentRank = 2,
|
|||
|
|
ReleaseDate = new DateTime(2022, 12, 3),
|
|||
|
|
Price = 999.99m
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
private readonly IRedisCacheService _cacheService;
|
|||
|
|
|
|||
|
|
public ProductsController(IRedisCacheService cacheService)
|
|||
|
|
{
|
|||
|
|
_cacheService = cacheService;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
[HttpGet]
|
|||
|
|
public async Task<ActionResult<PagedResponse<Product>>> GetProducts(
|
|||
|
|
[FromQuery] int? categoryId,
|
|||
|
|
[FromQuery] int page = 1,
|
|||
|
|
[FromQuery] int pageSize = 10,
|
|||
|
|
[FromQuery] string sortBy = "CurrentRank",
|
|||
|
|
[FromQuery] string order = "asc")
|
|||
|
|
{
|
|||
|
|
// 创建缓存键
|
|||
|
|
var cacheKey = $"products:list:{categoryId ?? 0}:{page}:{pageSize}:{sortBy}:{order}";
|
|||
|
|
|
|||
|
|
// 尝试从缓存获取数据
|
|||
|
|
var cachedResult = await _cacheService.GetAsync<PagedResponse<Product>>(cacheKey);
|
|||
|
|
if (cachedResult != null)
|
|||
|
|
{
|
|||
|
|
return Ok(cachedResult);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var query = _products.AsEnumerable();
|
|||
|
|
|
|||
|
|
if (categoryId.HasValue)
|
|||
|
|
{
|
|||
|
|
query = query.Where(p => p.CategoryId == categoryId.Value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 排序
|
|||
|
|
query = sortBy.ToLower() switch
|
|||
|
|
{
|
|||
|
|
"name" => order.ToLower() == "desc" ? query.OrderByDescending(p => p.Name) : query.OrderBy(p => p.Name),
|
|||
|
|
"manufacturer" => order.ToLower() == "desc" ? query.OrderByDescending(p => p.Manufacturer) : query.OrderBy(p => p.Manufacturer),
|
|||
|
|
"releasedate" => order.ToLower() == "desc" ? query.OrderByDescending(p => p.ReleaseDate) : query.OrderBy(p => p.ReleaseDate),
|
|||
|
|
"price" => order.ToLower() == "desc" ? query.OrderByDescending(p => p.Price) : query.OrderBy(p => p.Price),
|
|||
|
|
_ => order.ToLower() == "desc" ? query.OrderByDescending(p => p.CurrentRank) : query.OrderBy(p => p.CurrentRank)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
var totalCount = query.Count();
|
|||
|
|
var totalPages = (int)Math.Ceiling((double)totalCount / pageSize);
|
|||
|
|
var items = query.Skip((page - 1) * pageSize).Take(pageSize).ToList();
|
|||
|
|
|
|||
|
|
var result = new PagedResponse<Product>
|
|||
|
|
{
|
|||
|
|
Items = items,
|
|||
|
|
TotalCount = totalCount,
|
|||
|
|
PageNumber = page,
|
|||
|
|
PageSize = pageSize,
|
|||
|
|
TotalPages = totalPages
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 将结果存入缓存,设置5分钟过期时间
|
|||
|
|
await _cacheService.SetAsync(cacheKey, result, TimeSpan.FromMinutes(5));
|
|||
|
|
|
|||
|
|
return Ok(result);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
[HttpGet("{id}")]
|
|||
|
|
public async Task<ActionResult<ApiResponse<Product>>> GetProduct(int id)
|
|||
|
|
{
|
|||
|
|
// 创建缓存键
|
|||
|
|
var cacheKey = $"product:detail:{id}";
|
|||
|
|
|
|||
|
|
// 尝试从缓存获取数据
|
|||
|
|
var cachedResult = await _cacheService.GetAsync<ApiResponse<Product>>(cacheKey);
|
|||
|
|
if (cachedResult != null)
|
|||
|
|
{
|
|||
|
|
return Ok(cachedResult);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var product = _products.FirstOrDefault(p => p.Id == id);
|
|||
|
|
if (product == null)
|
|||
|
|
{
|
|||
|
|
var notFoundResponse = new ApiResponse<Product>
|
|||
|
|
{
|
|||
|
|
Success = false,
|
|||
|
|
Message = "未找到指定的产品"
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 缓存未找到的结果,设置较短过期时间
|
|||
|
|
await _cacheService.SetAsync(cacheKey, notFoundResponse, TimeSpan.FromMinutes(1));
|
|||
|
|
|
|||
|
|
return NotFound(notFoundResponse);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var result = new ApiResponse<Product>
|
|||
|
|
{
|
|||
|
|
Data = product
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 将结果存入缓存,设置15分钟过期时间
|
|||
|
|
await _cacheService.SetAsync(cacheKey, result, TimeSpan.FromMinutes(15));
|
|||
|
|
|
|||
|
|
return Ok(result);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
[HttpGet("search")]
|
|||
|
|
public async Task<ActionResult<PagedResponse<Product>>> SearchProducts(
|
|||
|
|
[FromQuery] string q,
|
|||
|
|
[FromQuery] int? categoryId,
|
|||
|
|
[FromQuery] string? manufacturer,
|
|||
|
|
[FromQuery] int? minScore,
|
|||
|
|
[FromQuery] int? maxScore,
|
|||
|
|
[FromQuery] int page = 1,
|
|||
|
|
[FromQuery] int pageSize = 10)
|
|||
|
|
{
|
|||
|
|
// 创建缓存键
|
|||
|
|
var cacheKey = $"products:search:{q ?? ""}:{categoryId ?? 0}:{manufacturer ?? ""}:{minScore ?? 0}:{maxScore ?? 0}:{page}:{pageSize}";
|
|||
|
|
|
|||
|
|
// 尝试从缓存获取数据
|
|||
|
|
var cachedResult = await _cacheService.GetAsync<PagedResponse<Product>>(cacheKey);
|
|||
|
|
if (cachedResult != null)
|
|||
|
|
{
|
|||
|
|
return Ok(cachedResult);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var query = _products.AsEnumerable();
|
|||
|
|
|
|||
|
|
if (!string.IsNullOrWhiteSpace(q))
|
|||
|
|
{
|
|||
|
|
query = query.Where(p =>
|
|||
|
|
p.Name.Contains(q, StringComparison.OrdinalIgnoreCase) ||
|
|||
|
|
p.Model.Contains(q, StringComparison.OrdinalIgnoreCase) ||
|
|||
|
|
p.Manufacturer.Contains(q, StringComparison.OrdinalIgnoreCase));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (categoryId.HasValue)
|
|||
|
|
{
|
|||
|
|
query = query.Where(p => p.CategoryId == categoryId.Value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!string.IsNullOrWhiteSpace(manufacturer))
|
|||
|
|
{
|
|||
|
|
query = query.Where(p =>
|
|||
|
|
p.Manufacturer.Equals(manufacturer, StringComparison.OrdinalIgnoreCase));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 注意:这里我们使用CurrentRank作为性能分数的替代,因为实际产品中没有性能分数字段
|
|||
|
|
if (minScore.HasValue)
|
|||
|
|
{
|
|||
|
|
query = query.Where(p => (100 - p.CurrentRank) >= minScore.Value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (maxScore.HasValue)
|
|||
|
|
{
|
|||
|
|
query = query.Where(p => (100 - p.CurrentRank) <= maxScore.Value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var totalCount = query.Count();
|
|||
|
|
var totalPages = (int)Math.Ceiling((double)totalCount / pageSize);
|
|||
|
|
var items = query.Skip((page - 1) * pageSize).Take(pageSize).ToList();
|
|||
|
|
|
|||
|
|
var result = new PagedResponse<Product>
|
|||
|
|
{
|
|||
|
|
Items = items,
|
|||
|
|
TotalCount = totalCount,
|
|||
|
|
PageNumber = page,
|
|||
|
|
PageSize = pageSize,
|
|||
|
|
TotalPages = totalPages
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 将结果存入缓存,设置3分钟过期时间(搜索结果变化较快)
|
|||
|
|
await _cacheService.SetAsync(cacheKey, result, TimeSpan.FromMinutes(3));
|
|||
|
|
|
|||
|
|
return Ok(result);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|