初始化
Some checks failed
CI/CD Pipeline / 测试 (18.x) (push) Has been cancelled
CI/CD Pipeline / 测试 (20.x) (push) Has been cancelled
CI/CD Pipeline / 安全检查 (push) Has been cancelled
CI/CD Pipeline / 部署 (push) Has been cancelled
CI/CD Pipeline / 通知 (push) Has been cancelled

This commit is contained in:
2025-11-03 19:47:36 +08:00
parent 7a04b85667
commit f25b0307db
454 changed files with 37064 additions and 4544 deletions

View File

@@ -3,15 +3,6 @@ using HardwarePerformance.Core.Entities;
namespace HardwarePerformance.Infrastructure.Data
{
/// <summary>
/// 基础实体类
/// </summary>
public abstract class BaseEntity
{
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
}
/// <summary>
/// 应用程序数据库上下文
/// </summary>

View File

@@ -51,19 +51,19 @@ namespace HardwarePerformance.Infrastructure.Data
{
Name = "Geekbench",
Description = "跨平台处理器和内存性能测试工具",
ApiUrl = "https://browser.geekbench.com/"
Url = "https://browser.geekbench.com/"
},
new DataSource
{
Name = "3DMark",
Description = "游戏和图形性能基准测试工具",
ApiUrl = "https://www.3dmark.com/"
Url = "https://www.3dmark.com/"
},
new DataSource
{
Name = "AnTuTu",
Description = "移动设备综合性能测试平台",
ApiUrl = "https://www.antutu.com/"
Url = "https://www.antutu.com/"
}
};
@@ -126,7 +126,7 @@ namespace HardwarePerformance.Infrastructure.Data
performanceScores.Add(new PerformanceScore
{
ProductId = cpu.Id,
BenchmarkType = "Single-Core",
TestName = "Single-Core",
Score = cpu.Name.Contains("A17") ? 2950 : cpu.Name.Contains("Snapdragon") ? 2300 : 2200,
TestDate = DateTime.Now,
DataSourceId = geekbenchSource.Id
@@ -135,7 +135,7 @@ namespace HardwarePerformance.Infrastructure.Data
performanceScores.Add(new PerformanceScore
{
ProductId = cpu.Id,
BenchmarkType = "Multi-Core",
TestName = "Multi-Core",
Score = cpu.Name.Contains("A17") ? 7200 : cpu.Name.Contains("Snapdragon") ? 7400 : 7500,
TestDate = DateTime.Now,
DataSourceId = geekbenchSource.Id
@@ -154,14 +154,14 @@ namespace HardwarePerformance.Infrastructure.Data
specifications.Add(new Specification
{
ProductId = cpu.Id,
Key = "制程工艺",
Name = "制程工艺",
Value = "3nm",
Unit = "nm"
});
specifications.Add(new Specification
{
ProductId = cpu.Id,
Key = "核心数",
Name = "核心数",
Value = "6",
Unit = "核"
});
@@ -171,14 +171,14 @@ namespace HardwarePerformance.Infrastructure.Data
specifications.Add(new Specification
{
ProductId = cpu.Id,
Key = "制程工艺",
Name = "制程工艺",
Value = "4nm",
Unit = "nm"
});
specifications.Add(new Specification
{
ProductId = cpu.Id,
Key = "核心数",
Name = "核心数",
Value = "8",
Unit = "核"
});
@@ -188,14 +188,14 @@ namespace HardwarePerformance.Infrastructure.Data
specifications.Add(new Specification
{
ProductId = cpu.Id,
Key = "制程工艺",
Name = "制程工艺",
Value = "4nm",
Unit = "nm"
});
specifications.Add(new Specification
{
ProductId = cpu.Id,
Key = "核心数",
Name = "核心数",
Value = "8",
Unit = "核"
});
@@ -242,7 +242,7 @@ namespace HardwarePerformance.Infrastructure.Data
performanceScores.Add(new PerformanceScore
{
ProductId = cpu.Id,
BenchmarkType = "Single-Core",
TestName = "Single-Core",
Score = cpu.Name.Contains("Intel") ? 3200 : 2300,
TestDate = DateTime.Now,
DataSourceId = geekbenchSource.Id
@@ -251,7 +251,7 @@ namespace HardwarePerformance.Infrastructure.Data
performanceScores.Add(new PerformanceScore
{
ProductId = cpu.Id,
BenchmarkType = "Multi-Core",
TestName = "Multi-Core",
Score = cpu.Name.Contains("Intel") ? 22000 : 30000,
TestDate = DateTime.Now,
DataSourceId = geekbenchSource.Id

View File

@@ -1,226 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace HardwarePerformance.Infrastructure.Data.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Categories",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Name = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false),
Description = table.Column<string>(type: "text", nullable: true),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Categories", x => x.Id);
});
migrationBuilder.CreateTable(
name: "DataSources",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Name = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false),
Description = table.Column<string>(type: "text", nullable: true),
ApiUrl = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: true),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_DataSources", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Products",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Name = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: false),
Model = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false),
Manufacturer = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false),
ReleaseDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
ImageUrl = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: true),
CategoryId = table.Column<int>(type: "int", nullable: false),
CurrentRank = table.Column<int>(type: "int", nullable: true),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Products", x => x.Id);
table.ForeignKey(
name: "FK_Products_Categories_CategoryId",
column: x => x.CategoryId,
principalTable: "Categories",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "PerformanceScores",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
ProductId = table.Column<int>(type: "int", nullable: false),
BenchmarkType = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: false),
Score = table.Column<decimal>(type: "decimal(10,2)", nullable: false),
TestDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
DataSourceId = table.Column<int>(type: "int", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_PerformanceScores", x => x.Id);
table.ForeignKey(
name: "FK_PerformanceScores_DataSources_DataSourceId",
column: x => x.DataSourceId,
principalTable: "DataSources",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_PerformanceScores_Products_ProductId",
column: x => x.ProductId,
principalTable: "Products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "RankingHistories",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
ProductId = table.Column<int>(type: "int", nullable: false),
Rank = table.Column<int>(type: "int", nullable: false),
CategoryId = table.Column<int>(type: "int", nullable: false),
RecordDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_RankingHistories", x => x.Id);
table.ForeignKey(
name: "FK_RankingHistories_Categories_CategoryId",
column: x => x.CategoryId,
principalTable: "Categories",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_RankingHistories_Products_ProductId",
column: x => x.ProductId,
principalTable: "Products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Specifications",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
ProductId = table.Column<int>(type: "int", nullable: false),
Key = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false),
Value = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: false),
Unit = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Specifications", x => x.Id);
table.ForeignKey(
name: "FK_Specifications_Products_ProductId",
column: x => x.ProductId,
principalTable: "Products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_PerformanceScores_BenchmarkType",
table: "PerformanceScores",
column: "BenchmarkType");
migrationBuilder.CreateIndex(
name: "IX_PerformanceScores_ProductId",
table: "PerformanceScores",
column: "ProductId");
migrationBuilder.CreateIndex(
name: "IX_Products_CategoryId",
table: "Products",
column: "CategoryId");
migrationBuilder.CreateIndex(
name: "IX_Products_Manufacturer",
table: "Products",
column: "Manufacturer");
migrationBuilder.CreateIndex(
name: "IX_Products_Model",
table: "Products",
column: "Model");
migrationBuilder.CreateIndex(
name: "IX_Products_Name",
table: "Products",
column: "Name");
migrationBuilder.CreateIndex(
name: "IX_RankingHistories_CategoryId",
table: "RankingHistories",
column: "CategoryId");
migrationBuilder.CreateIndex(
name: "IX_RankingHistories_ProductId",
table: "RankingHistories",
column: "ProductId");
migrationBuilder.CreateIndex(
name: "IX_Specifications_ProductId",
table: "Specifications",
column: "ProductId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "PerformanceScores");
migrationBuilder.DropTable(
name: "RankingHistories");
migrationBuilder.DropTable(
name: "Specifications");
migrationBuilder.DropTable(
name: "DataSources");
migrationBuilder.DropTable(
name: "Products");
migrationBuilder.DropTable(
name: "Categories");
}
}
}

View File

@@ -1,315 +0,0 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using HardwarePerformance.Infrastructure.Data;
#nullable disable
namespace HardwarePerformance.Infrastructure.Data.Migrations
{
[DbContext(typeof(AppDbContext))]
partial class AppDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
MySqlModelBuilderExtensions.UseCollation(modelBuilder, "utf8mb4_0900_ai_ci");
modelBuilder.Entity("HardwarePerformance.Core.Entities.Category", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.ToTable("Categories");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.DataSource", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("ApiUrl")
.HasMaxLength(500)
.HasColumnType("varchar(500)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.ToTable("DataSources");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.PerformanceScore", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("BenchmarkType")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("varchar(50)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<int>("DataSourceId")
.HasColumnType("int");
b.Property<int>("ProductId")
.HasColumnType("int");
b.Property<decimal>("Score")
.HasColumnType("decimal(10,2)");
b.Property<DateTime>("TestDate")
.HasColumnType("datetime(6)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.HasIndex("BenchmarkType");
b.HasIndex("ProductId");
b.ToTable("PerformanceScores");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.Product", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CategoryId")
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("ImageUrl")
.HasMaxLength(500)
.HasColumnType("varchar(500)");
b.Property<string>("Manufacturer")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<string>("Model")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int?>("CurrentRank")
.HasColumnType("int");
b.Property<DateTime>("ReleaseDate")
.HasColumnType("datetime(6)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.HasIndex("CategoryId");
b.HasIndex("Manufacturer");
b.HasIndex("Model");
b.HasIndex("Name");
b.ToTable("Products");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.RankingHistory", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CategoryId")
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<int>("ProductId")
.HasColumnType("int");
b.Property<int>("Rank")
.HasColumnType("int");
b.Property<DateTime>("RecordDate")
.HasColumnType("datetime(6)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.HasIndex("CategoryId");
b.HasIndex("ProductId");
b.ToTable("RankingHistories");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.Specification", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Key")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<int>("ProductId")
.HasColumnType("int");
b.Property<string>("Unit")
.HasMaxLength(50)
.HasColumnType("varchar(50)");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("varchar(500)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.HasIndex("ProductId");
b.ToTable("Specifications");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.PerformanceScore", b =>
{
b.HasOne("HardwarePerformance.Core.Entities.DataSource", "DataSource")
.WithMany()
.HasForeignKey("DataSourceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("HardwarePerformance.Core.Entities.Product", "Product")
.WithMany("PerformanceScores")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("DataSource");
b.Navigation("Product");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.Product", b =>
{
b.HasOne("HardwarePerformance.Core.Entities.Category", "Category")
.WithMany("Products")
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Category");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.RankingHistory", b =>
{
b.HasOne("HardwarePerformance.Core.Entities.Category", "Category")
.WithMany()
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("HardwarePerformance.Core.Entities.Product", "Product")
.WithMany("RankingHistories")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Category");
b.Navigation("Product");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.Specification", b =>
{
b.HasOne("HardwarePerformance.Core.Entities.Product", "Product")
.WithMany("Specifications")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.Category", b =>
{
b.Navigation("Products");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.Product", b =>
{
b.Navigation("PerformanceScores");
b.Navigation("RankingHistories");
b.Navigation("Specifications");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -1,6 +1,7 @@
using System.Data;
using MySql.Data.MySqlClient;
using HardwarePerformance.Core.Entities;
using Microsoft.Extensions.Configuration;
namespace HardwarePerformance.Infrastructure.Data;
@@ -202,4 +203,63 @@ public class SimpleAppDbContext
cmd.CommandText = insertSpecifications;
await cmd.ExecuteNonQueryAsync();
}
public async Task<List<object>> GetCategoriesAsync()
{
var categories = new List<object>();
using var connection = new MySqlConnection(_connectionString);
await connection.OpenAsync();
using var cmd = new MySqlCommand("SELECT * FROM Categories", connection);
using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
categories.Add(new
{
Id = reader.GetInt32("Id"),
Name = reader.GetString("Name"),
Description = reader.IsDBNull("Description") ? null : reader.GetString("Description"),
CreatedAt = reader.GetDateTime("CreatedAt")
});
}
return categories;
}
public async Task<List<object>> GetProductsAsync(int categoryId = 0, int page = 1, int pageSize = 10)
{
var products = new List<object>();
using var connection = new MySqlConnection(_connectionString);
await connection.OpenAsync();
var offset = (page - 1) * pageSize;
var query = categoryId > 0
? $"SELECT p.*, c.Name as CategoryName FROM Products p LEFT JOIN Categories c ON p.CategoryId = c.Id WHERE p.CategoryId = {categoryId} LIMIT {pageSize} OFFSET {offset}"
: $"SELECT p.*, c.Name as CategoryName FROM Products p LEFT JOIN Categories c ON p.CategoryId = c.Id LIMIT {pageSize} OFFSET {offset}";
using var cmd = new MySqlCommand(query, connection);
using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
products.Add(new
{
Id = reader.GetInt32("Id"),
Name = reader.GetString("Name"),
Model = reader.IsDBNull("Model") ? null : reader.GetString("Model"),
Manufacturer = reader.IsDBNull("Manufacturer") ? null : reader.GetString("Manufacturer"),
ImageUrl = reader.IsDBNull("ImageUrl") ? null : reader.GetString("ImageUrl"),
ReleaseDate = reader.IsDBNull("ReleaseDate") ? (DateTime?)null : reader.GetDateTime("ReleaseDate"),
CategoryId = reader.IsDBNull("CategoryId") ? (int?)null : reader.GetInt32("CategoryId"),
CategoryName = reader.IsDBNull("CategoryName") ? null : reader.GetString("CategoryName"),
CurrentRank = reader.IsDBNull("CurrentRank") ? (int?)null : reader.GetInt32("CurrentRank"),
CreatedAt = reader.GetDateTime("CreatedAt")
});
}
return products;
}
}