初始化数据库表配置

This commit is contained in:
西街长安 2024-10-23 01:33:18 +00:00 committed by 南浔
parent 7b22e66310
commit 89d74e83b1
27 changed files with 1723 additions and 48 deletions

View File

@ -7,7 +7,19 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Controllers\" />
<Folder Include="Services\" />
<Folder Include="Tools\" />
<Folder Include="Config\" />
</ItemGroup>
</Project> </Project>

View File

@ -1,33 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace Apimanager_backend.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
}

View File

@ -0,0 +1,26 @@
using Apimanager_backend.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Apimanager_backend.Data
{
public class ApiCallLogConfig : IEntityTypeConfiguration<ApiCallLog>
{
public void Configure(EntityTypeBuilder<ApiCallLog> builder)
{
//主键
builder.HasKey(x => x.Id);
//自增
builder.Property(x => x.Id)
.ValueGeneratedOnAdd();
//外键API
builder.HasOne(x => x.Api)
.WithMany(u => u.ApiCalls)
.HasForeignKey(x => x.ApiId);
//外键User
builder.HasOne(x => x.User)
.WithMany(u => u.CallLogs)
.HasForeignKey(x => x.UserId);
}
}
}

View File

@ -0,0 +1,23 @@
using Apimanager_backend.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Apimanager_backend.Data
{
public class ApiConfig : IEntityTypeConfiguration<Api>
{
public void Configure(EntityTypeBuilder<Api> builder)
{
//主键
builder.HasKey(x => x.Id);
//自增
builder.Property(x => x.Id)
.ValueGeneratedOnAdd();
//外键
builder.HasOne(x => x.Package)
.WithMany(u => u.Apis)
.HasForeignKey(x => x.PackageId);
}
}
}

View File

@ -0,0 +1,30 @@
using Apimanager_backend.Models;
using Microsoft.EntityFrameworkCore;
using System.Reflection;
namespace Apimanager_backend.Data
{
public class ApiContext:DbContext
{
//API表
public DbSet<Api> Apis { get; set; }
//用户表
public DbSet<User> Users { get; set; }
//API调用日志
public DbSet<ApiCallLog> CallLogs { get; set; }
//套餐表
public DbSet<Apipackage> Apipackages { get; set; }
//操作日志表
public DbSet<OperationLog> OperationLogs { get; set; }
//订单表
public DbSet<Order> Orders { get; set; }
//用户已订购套餐表
public DbSet<UserPackage> UserPackages { get; set; }
public ApiContext(DbContextOptions<ApiContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfigurationsFromAssembly(typeof(ApiContext).Assembly);
}
}
}

View File

@ -0,0 +1,22 @@
using Apimanager_backend.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Apimanager_backend.Data
{
public class OperationLogConfig : IEntityTypeConfiguration<OperationLog>
{
public void Configure(EntityTypeBuilder<OperationLog> builder)
{
//主键
builder.HasKey(x => x.Id);
//自增
builder.Property(x => x.Id)
.ValueGeneratedOnAdd();
//外键
builder.HasOne(x => x.User)
.WithMany(u => u.operationLogs)
.HasForeignKey(x => x.UserId);
}
}
}

View File

@ -0,0 +1,28 @@
using Apimanager_backend.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Apimanager_backend.Data
{
public class OrderConfig : IEntityTypeConfiguration<Order>
{
public void Configure(EntityTypeBuilder<Order> builder)
{
//主键
builder.HasKey(x => x.Id);
//自增
builder.Property(x => x.Id)
.ValueGeneratedOnAdd();
//唯一索引
builder.HasIndex(x => x.OrderNumber)
.IsUnique();
//唯一索引
builder.HasIndex(x => x.ThirdPartyOrderId)
.IsUnique();
//外键
builder.HasOne(x => x.User)
.WithMany(u => u.Orders)
.HasForeignKey(x => x.UserId);
}
}
}

View File

@ -0,0 +1,23 @@
using Apimanager_backend.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Apimanager_backend.Data
{
public class UserConfig : IEntityTypeConfiguration<User>
{
public void Configure(EntityTypeBuilder<User> builder)
{
//主键
builder.HasKey(x => x.Id);
//自增
builder.Property(x => x.Id)
.ValueGeneratedOnAdd();
//唯一索引
builder.HasIndex(x => x.Username)
.IsUnique();
builder.HasIndex(x => x.Email)
.IsUnique();
}
}
}

View File

@ -0,0 +1,25 @@
using Apimanager_backend.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Apimanager_backend.Data
{
public class UserPackageConfig : IEntityTypeConfiguration<UserPackage>
{
public void Configure(EntityTypeBuilder<UserPackage> builder)
{
//主键
builder.HasKey(x => x.Id);
//自增
builder.Property(x => x.Id)
.ValueGeneratedOnAdd();
//外键
builder.HasOne(x => x.User)
.WithMany(u => u.Packages)
.HasForeignKey(x => x.UserId);
builder.HasOne(x => x.Package)
.WithMany(u => u.Packages)
.HasForeignKey(x => x.PackageId);
}
}
}

View File

@ -0,0 +1,378 @@
// <auto-generated />
using System;
using Apimanager_backend.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Apimanager_backend.Migrations
{
[DbContext(typeof(ApiContext))]
[Migration("20241024162342_Init-Database")]
partial class InitDatabase
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Endpoint")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsThirdParty")
.HasColumnType("tinyint(1)");
b.Property<int>("Method")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int?>("PackageId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PackageId");
b.ToTable("Apis");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<int>("CallResult")
.HasColumnType("int");
b.Property<DateTime>("CallTime")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ApiId");
b.HasIndex("UserId");
b.ToTable("CallLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CallLimit")
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<DateTime>("ExpiryDate")
.HasColumnType("datetime(6)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<decimal>("Price")
.HasColumnType("decimal(65,30)");
b.HasKey("Id");
b.ToTable("Apipackages");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("IpAddress")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("varchar(45)");
b.Property<string>("Operation")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<int>("TargetId")
.HasColumnType("int");
b.Property<string>("TargetType")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("varchar(50)");
b.Property<string>("UserAgent")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("OperationLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<decimal>("Amount")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<string>("OrderNumber")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<int>("OrderType")
.HasColumnType("int");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("ThirdPartyOrderId")
.HasColumnType("varchar(255)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("OrderNumber")
.IsUnique();
b.HasIndex("ThirdPartyOrderId")
.IsUnique();
b.HasIndex("UserId");
b.ToTable("Orders");
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<decimal>("Balance")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<bool>("IsBan")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<string>("PassHash")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("varchar(255)");
b.Property<int>("Role")
.HasColumnType("int");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("varchar(255)");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique();
b.HasIndex("Username")
.IsUnique();
b.ToTable("Users");
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("PackageId")
.HasColumnType("int");
b.Property<DateTime>("PurchasedAt")
.HasColumnType("datetime(6)");
b.Property<int>("RemainingCalls")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PackageId");
b.HasIndex("UserId");
b.ToTable("UserPackages");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Apis")
.HasForeignKey("PackageId");
b.Navigation("Package");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiCalls")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("CallLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("operationLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Orders")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Packages")
.HasForeignKey("PackageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Packages")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Package");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Navigation("ApiCalls");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Navigation("Apis");
b.Navigation("Packages");
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Navigation("CallLogs");
b.Navigation("Orders");
b.Navigation("Packages");
b.Navigation("operationLogs");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,295 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Apimanager_backend.Migrations
{
/// <inheritdoc />
public partial class InitDatabase : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "Apipackages",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Name = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
CallLimit = table.Column<int>(type: "int", nullable: false),
Price = table.Column<decimal>(type: "decimal(65,30)", nullable: false),
ExpiryDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Apipackages", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Username = table.Column<string>(type: "varchar(255)", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Email = table.Column<string>(type: "varchar(255)", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
PassHash = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Role = table.Column<int>(type: "int", nullable: false),
IsBan = table.Column<bool>(type: "tinyint(1)", nullable: false),
IsDelete = table.Column<bool>(type: "tinyint(1)", nullable: false),
Balance = table.Column<decimal>(type: "decimal(65,30)", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "Apis",
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)
.Annotation("MySql:CharSet", "utf8mb4"),
Endpoint = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Method = table.Column<int>(type: "int", nullable: false),
PackageId = table.Column<int>(type: "int", nullable: true),
IsThirdParty = table.Column<bool>(type: "tinyint(1)", nullable: false),
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false),
IsDelete = table.Column<bool>(type: "tinyint(1)", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Apis", x => x.Id);
table.ForeignKey(
name: "FK_Apis_Apipackages_PackageId",
column: x => x.PackageId,
principalTable: "Apipackages",
principalColumn: "Id");
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "OperationLogs",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
UserId = table.Column<int>(type: "int", nullable: false),
Operation = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
TargetType = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
TargetId = table.Column<int>(type: "int", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
IpAddress = table.Column<string>(type: "varchar(45)", maxLength: 45, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
UserAgent = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Description = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_OperationLogs", x => x.Id);
table.ForeignKey(
name: "FK_OperationLogs_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "Orders",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
UserId = table.Column<int>(type: "int", nullable: false),
OrderNumber = table.Column<string>(type: "varchar(255)", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
ThirdPartyOrderId = table.Column<string>(type: "varchar(255)", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Amount = table.Column<decimal>(type: "decimal(65,30)", nullable: false),
OrderType = table.Column<int>(type: "int", nullable: false),
Status = 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),
Description = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_Orders", x => x.Id);
table.ForeignKey(
name: "FK_Orders_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "UserPackages",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
UserId = table.Column<int>(type: "int", nullable: false),
PackageId = table.Column<int>(type: "int", nullable: false),
RemainingCalls = table.Column<int>(type: "int", nullable: false),
PurchasedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_UserPackages", x => x.Id);
table.ForeignKey(
name: "FK_UserPackages_Apipackages_PackageId",
column: x => x.PackageId,
principalTable: "Apipackages",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_UserPackages_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "CallLogs",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
UserId = table.Column<int>(type: "int", nullable: false),
ApiId = table.Column<int>(type: "int", nullable: false),
CallTime = table.Column<DateTime>(type: "datetime(6)", nullable: false),
CallResult = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CallLogs", x => x.Id);
table.ForeignKey(
name: "FK_CallLogs_Apis_ApiId",
column: x => x.ApiId,
principalTable: "Apis",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_CallLogs_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateIndex(
name: "IX_Apis_PackageId",
table: "Apis",
column: "PackageId");
migrationBuilder.CreateIndex(
name: "IX_CallLogs_ApiId",
table: "CallLogs",
column: "ApiId");
migrationBuilder.CreateIndex(
name: "IX_CallLogs_UserId",
table: "CallLogs",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_OperationLogs_UserId",
table: "OperationLogs",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_Orders_OrderNumber",
table: "Orders",
column: "OrderNumber",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Orders_ThirdPartyOrderId",
table: "Orders",
column: "ThirdPartyOrderId",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Orders_UserId",
table: "Orders",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_UserPackages_PackageId",
table: "UserPackages",
column: "PackageId");
migrationBuilder.CreateIndex(
name: "IX_UserPackages_UserId",
table: "UserPackages",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_Users_Email",
table: "Users",
column: "Email",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Users_Username",
table: "Users",
column: "Username",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "CallLogs");
migrationBuilder.DropTable(
name: "OperationLogs");
migrationBuilder.DropTable(
name: "Orders");
migrationBuilder.DropTable(
name: "UserPackages");
migrationBuilder.DropTable(
name: "Apis");
migrationBuilder.DropTable(
name: "Users");
migrationBuilder.DropTable(
name: "Apipackages");
}
}
}

View File

@ -0,0 +1,375 @@
// <auto-generated />
using System;
using Apimanager_backend.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Apimanager_backend.Migrations
{
[DbContext(typeof(ApiContext))]
partial class ApiContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Endpoint")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsThirdParty")
.HasColumnType("tinyint(1)");
b.Property<int>("Method")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int?>("PackageId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PackageId");
b.ToTable("Apis");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<int>("CallResult")
.HasColumnType("int");
b.Property<DateTime>("CallTime")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ApiId");
b.HasIndex("UserId");
b.ToTable("CallLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CallLimit")
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<DateTime>("ExpiryDate")
.HasColumnType("datetime(6)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<decimal>("Price")
.HasColumnType("decimal(65,30)");
b.HasKey("Id");
b.ToTable("Apipackages");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("IpAddress")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("varchar(45)");
b.Property<string>("Operation")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<int>("TargetId")
.HasColumnType("int");
b.Property<string>("TargetType")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("varchar(50)");
b.Property<string>("UserAgent")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("OperationLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<decimal>("Amount")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<string>("OrderNumber")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<int>("OrderType")
.HasColumnType("int");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("ThirdPartyOrderId")
.HasColumnType("varchar(255)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("OrderNumber")
.IsUnique();
b.HasIndex("ThirdPartyOrderId")
.IsUnique();
b.HasIndex("UserId");
b.ToTable("Orders");
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<decimal>("Balance")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<bool>("IsBan")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<string>("PassHash")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("varchar(255)");
b.Property<int>("Role")
.HasColumnType("int");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("varchar(255)");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique();
b.HasIndex("Username")
.IsUnique();
b.ToTable("Users");
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("PackageId")
.HasColumnType("int");
b.Property<DateTime>("PurchasedAt")
.HasColumnType("datetime(6)");
b.Property<int>("RemainingCalls")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PackageId");
b.HasIndex("UserId");
b.ToTable("UserPackages");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Apis")
.HasForeignKey("PackageId");
b.Navigation("Package");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiCalls")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("CallLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("operationLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Orders")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Packages")
.HasForeignKey("PackageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Packages")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Package");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Navigation("ApiCalls");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Navigation("Apis");
b.Navigation("Packages");
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Navigation("CallLogs");
b.Navigation("Orders");
b.Navigation("Packages");
b.Navigation("operationLogs");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,59 @@
using Apimanager_backend.Data;
using System.ComponentModel.DataAnnotations;
namespace Apimanager_backend.Models
{
public class Api
{
/// <summary>
/// 主键,自增
/// </summary>
public int Id { get; set; }
/// <summary>
/// API名称
/// </summary>
[MaxLength(200)]
[Required]
public string Name { get; set; } // varchar(20)
/// <summary>
/// API地址
/// </summary>
[Required]
public string Endpoint { get; set; } // varchar(255)
/// <summary>
/// 调用方法
/// </summary>
public ApiMethod Method { get; set; } // enum('GET','POST','PUT', 'DELETE')
/// <summary>
/// 套餐Id默认为空免费无限制
/// </summary>
public int? PackageId { get; set; } // int? 使其可为null
/// <summary>
/// 是否第三方API
/// </summary>
public bool IsThirdParty { get; set; } // boolean
/// <summary>
/// 是否启用
/// </summary>
public bool IsActive { get; set; } // boolean
/// <summary>
/// 是否删除
/// </summary>
public bool IsDelete { get; set; } // boolean
/// <summary>
/// 创建时间,默认当前时间
/// </summary>
public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // timestamp
//导航属性
public Apipackage? Package { get; set; }
public ICollection<ApiCallLog> ApiCalls { get; set; }
}
}

View File

@ -0,0 +1,35 @@
namespace Apimanager_backend.Models
{
public class ApiCallLog
{
/// <summary>
/// 主键,自增
/// </summary>
public int Id { get; set; }
/// <summary>
/// 外键用户ID
/// </summary>
public int UserId { get; set; }
/// <summary>
/// 外键API ID
/// </summary>
public int ApiId { get; set; }
/// <summary>
/// 调用时间,默认当前时间
/// </summary>
public DateTime CallTime { get; set; } = DateTime.UtcNow; // Timestamp
/// <summary>
/// 调用结果状态码
/// </summary>
public int CallResult { get; set; } // 调用结果状态码
//导航属性
public User? User { get; set; }
public Api? Api { get; set; }
}
}

View File

@ -0,0 +1,10 @@
namespace Apimanager_backend.Models
{
public enum ApiMethod
{
GET,
POST,
PUT,
DELETE
}
}

View File

@ -0,0 +1,44 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
namespace Apimanager_backend.Models
{
public class Apipackage
{
/// <summary>
/// 主键,自增
/// </summary>
[Key]
public int Id { get; set; }
/// <summary>
/// 套餐名称
/// </summary>
[MaxLength(20)]
public string Name { get; set; } // varchar(20)
/// <summary>
/// 最大调用次数
/// </summary>
public int CallLimit { get; set; } // int
/// <summary>
/// 价格
/// </summary>
public decimal Price { get; set; } // decimal(10,2)
/// <summary>
/// 套餐过期时间,可用于控制套餐是否过期
/// </summary>
public DateTime ExpiryDate { get; set; } // timestamp
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // timestamp
//导航属性
public ICollection<Api> Apis { get; set; }
public ICollection<UserPackage> Packages { get; set; }
}
}

View File

@ -0,0 +1,61 @@
using Microsoft.AspNetCore.Antiforgery;
using System.ComponentModel.DataAnnotations;
namespace Apimanager_backend.Models
{
public class OperationLog
{
/// <summary>
/// 主键,自增
/// </summary>
public int Id { get; set; }
/// <summary>
/// 操作人ID操作者的用户ID通常是管理员
/// </summary>
public int UserId { get; set; }
/// <summary>
/// 操作类型,描述操作的具体内容
/// </summary>
[Required]
[MaxLength(20)]
public string Operation { get; set; } // varchar(20)
/// <summary>
/// 目标类型,操作的对象类型
/// </summary>
[Required]
[MaxLength(50)]
public string TargetType { get; set; } // varchar(50)
/// <summary>
/// 目标对象ID操作对象的具体ID
/// </summary>
public int TargetId { get; set; }
/// <summary>
/// 操作时间,操作发生时间
/// </summary>
public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // timestamp
/// <summary>
/// 操作来源IP
/// </summary>
[MaxLength(45)]
public string IpAddress { get; set; } // varchar(45)
/// <summary>
/// 操作设备信息
/// </summary>
public string UserAgent { get; set; } // varchar(255)
/// <summary>
/// 操作描述,可选的详细说明,解释操作原因等
/// </summary>
public string Description { get; set; } // varchar(255)
//导航属性
public User? User { get; set; }
}
}

View File

@ -0,0 +1,62 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
namespace Apimanager_backend.Models
{
public class Order
{
/// <summary>
/// 主键,自增
/// </summary>
public int Id { get; set; }
/// <summary>
/// 外键用户ID
/// </summary>
public int UserId { get; set; }
/// <summary>
/// 订单号,唯一
/// </summary>
[Required]
public string OrderNumber { get; set; } // varchar(50)
/// <summary>
/// 第三方系统订单编号
/// </summary>
public string? ThirdPartyOrderId { get; set; } // varchar(100)
/// <summary>
/// 订单金额
/// </summary>
public decimal Amount { get; set; } // decimal(10, 2)
/// <summary>
/// 订单类型
/// </summary>
public OrderType OrderType { get; set; } // enum('Recharge','Purchase','Refund')
/// <summary>
/// 订单状态
/// </summary>
public OrderStatus Status { get; set; } // enum('Pending','Completed','Cancelled','Failed')
/// <summary>
/// 创建时间,订单创建时间
/// </summary>
public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // timestamp
/// <summary>
/// 更新时间,订单状态更新时间
/// </summary>
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; // timestamp
/// <summary>
/// 订单描述,可选的详细信息
/// </summary>
public string? Description { get; set; } // varchar(255)
//导航属性
public User? User { get; set; }
}
}

View File

@ -0,0 +1,10 @@
namespace Apimanager_backend.Models
{
public enum OrderStatus
{
Pending,
Completed,
Cancelled,
Failed
}
}

View File

@ -0,0 +1,9 @@
namespace Apimanager_backend.Models
{
public enum OrderType
{
Recharge,
Purchase,
Refund
}
}

View File

@ -0,0 +1,60 @@
using System.ComponentModel.DataAnnotations;
namespace Apimanager_backend.Models
{
public class User
{
/// <summary>
/// 用户ID主键自增
/// </summary>
public int Id { get; set; }
/// <summary>
/// 用户名,唯一
/// </summary>
[Required]
public string Username { get; set; } // varchar(20)
/// <summary>
/// 邮箱,唯一
/// </summary>
public string Email { get; set; } // varchar(20)
/// <summary>
/// 密码哈希
/// </summary>
[Required]
[MaxLength(255)]
public string PassHash { get; set; } // varchar(255)
/// <summary>
/// 用户角色
/// </summary>
public UserRole Role { get; set; } // Enum('Admin','User')
/// <summary>
/// 是否禁用
/// </summary>
public bool IsBan { get; set; } // boolean
/// <summary>
/// 是否删除
/// </summary>
public bool IsDelete { get; set; } // boolean
/// <summary>
/// 余额
/// </summary>
public decimal Balance { get; set; } // Decimal(10)
/// <summary>
/// 创建时间,默认当前时间
/// </summary>
public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // Timestamp
//导航属性
public ICollection<UserPackage> Packages { get; set; }
public ICollection<OperationLog> operationLogs { get; set; }
public ICollection<ApiCallLog> CallLogs { get; set; }
public ICollection<Order> Orders { get; set; }
}
}

View File

@ -0,0 +1,33 @@
namespace Apimanager_backend.Models
{
public class UserPackage
{/// <summary>
/// 主键,自增
/// </summary>
public int Id { get; set; }
/// <summary>
/// 外键用户ID
/// </summary>
public int UserId { get; set; }
/// <summary>
/// 外键套餐ID
/// </summary>
public int PackageId { get; set; }
/// <summary>
/// 剩余调用次数
/// </summary>
public int RemainingCalls { get; set; }
/// <summary>
/// 购买时间
/// </summary>
public DateTime PurchasedAt { get; set; } = DateTime.UtcNow; // timestamp
//导航属性
public User? User { get; set; }
public Apipackage? Package { get; set; }
}
}

View File

@ -0,0 +1,8 @@
namespace Apimanager_backend.Models
{
public enum UserRole
{
Admin = 0,
User = 1
}
}

View File

@ -1,7 +1,21 @@
using Apimanager_backend.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
// Add services to the container. // Add services to the container.
IConfiguration configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
string? constr = configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApiContext>(option =>
option.UseMySql(constr, MySqlServerVersion.AutoDetect(constr))
);
builder.Services.AddControllers(); builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddEndpointsApiExplorer();

View File

@ -1,13 +0,0 @@
namespace Apimanager_backend
{
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}
}

View File

@ -5,5 +5,8 @@
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Warning"
} }
}, },
"AllowedHosts": "*" "AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection": "server=192.168.5.200;username=root;password=768788Dyw@;port=3306;database=api_billing_system;SslMode=Preferred;"
}
} }

View File

@ -1 +1,77 @@
# Apimanager_backend ## 项目背景
简单描述该API的背景、用途及目标用户。
## 功能概述
1. ##### 用户管理
- 登录、注册
- 用户账号信息管理
- 用户充值、消费记录查询
2. ##### API访问管理
- 用户密钥生成和管理
- API管理
- 调用次数和消费金额限制
- 付费套餐管理
3. ##### 支付模块
4. ##### 订单模块
- 订单生成
- 消费提醒(超额/余额不足)
5. ##### 系统监控模块
- 调用记录
- 异常告警
## 系统依赖
- **.NET 6.0 或更高版本**
- **Entity Framework Core** 用于数据库操作
- **MySQL** 作为后端数据库
- **Swagger** 用于API文档自动生成
- **JWT** 实现用户认证和授权
## 项目结构
```perl
api-billing-system/
├── API/ # API控制器及路由
├── Services/ # 业务逻辑层
├── Models/ # 数据模型定义
├── Data/ # 数据库上下文及迁移文件
├── Config/ # 系统配置文件
├── Tests/ # 单元测试及集成测试
├── Tools/ # 工具类
└── README.md # 项目文档(本文件)
```
## 模块划分
1. **API 控制器**
- 负责处理用户请求并返回结果。
- 提供如用户注册、登录、查询调用次数等API端点。
1. ##### **业务逻辑层Services**
- 负责具体业务逻辑,如套餐管理、消费计算等。
- 实现支付网关集成。
1. **数据模型Models**
- 定义数据库中的表结构,如用户表、订单表等。
1. **数据库Data**
- 提供数据库连接及操作支持。
- 包含数据库上下文类及数据库迁移文件。