Browse Source

更新字段

feature/x1-web-request
root 5 days ago
parent
commit
b493e2ea4b
  1. 69
      src/X1.Application/Features/NetworkStackConfigs/Commands/CreateNetworkStackConfig/CreateNetworkStackConfigCommandHandler.cs
  2. 5
      src/X1.Application/Features/NetworkStackConfigs/Commands/CreateNetworkStackConfig/CreateNetworkStackConfigResponse.cs
  3. 2
      src/X1.Domain/Common/OperationResult.cs
  4. 9
      src/X1.Domain/Entities/NetworkProfile/NetworkStackConfig.cs
  5. 10
      src/X1.Domain/Repositories/NetworkProfile/INetworkStackConfigRepository.cs
  6. 2
      src/X1.Infrastructure/Configurations/NetworkProfile/NetworkStackConfigConfiguration.cs
  7. 923
      src/X1.Infrastructure/Migrations/20250729142128_AddNetworkCodeToNetworkStackConfig.Designer.cs
  8. 52
      src/X1.Infrastructure/Migrations/20250729142128_AddNetworkCodeToNetworkStackConfig.cs
  9. 929
      src/X1.Infrastructure/Migrations/20250729144236_AddNetworkStackCode.Designer.cs
  10. 76
      src/X1.Infrastructure/Migrations/20250729144236_AddNetworkStackCode.cs
  11. 20
      src/X1.Infrastructure/Migrations/AppDbContextModelSnapshot.cs
  12. 16
      src/X1.Infrastructure/Repositories/NetworkProfile/NetworkStackConfigRepository.cs
  13. 4
      src/X1.WebAPI/Properties/launchSettings.json
  14. 3
      src/X1.WebUI/src/services/networkStackConfigService.ts

69
src/X1.Application/Features/NetworkStackConfigs/Commands/CreateNetworkStackConfig/CreateNetworkStackConfigCommandHandler.cs

@ -60,9 +60,32 @@ public class CreateNetworkStackConfigCommandHandler : IRequestHandler<CreateNetw
return OperationResult<CreateNetworkStackConfigResponse>.CreateFailure("用户未认证,无法创建网络栈配置");
}
// 生成网络栈编码
var networkStackCode = await GenerateNetworkStackCodeAsync(cancellationToken);
// 检查编码是否重复,如果重复则重新生成(最多重试3次)
var maxRetries = 3;
var retryCount = 0;
while (await _networkStackConfigRepository.CodeExistsAsync(networkStackCode, cancellationToken) && retryCount < maxRetries)
{
retryCount++;
_logger.LogWarning("网络栈编码重复,重新生成,重试次数: {RetryCount}, 编码: {NetworkStackCode}", retryCount, networkStackCode);
// 等待一小段时间后重新生成
await Task.Delay(10, cancellationToken);
networkStackCode = await GenerateNetworkStackCodeAsync(cancellationToken);
}
if (retryCount >= maxRetries)
{
_logger.LogError("网络栈编码生成失败,重试次数已达上限: {MaxRetries}", maxRetries);
return OperationResult<CreateNetworkStackConfigResponse>.CreateFailure("网络栈编码生成失败,请稍后重试");
}
// 创建网络栈配置实体
var networkStackConfig = NetworkStackConfig.Create(
networkStackName: request.NetworkStackName,
networkStackCode: networkStackCode,
createdBy: currentUserId,
ranId: request.RanId,
description: request.Description,
@ -123,6 +146,7 @@ public class CreateNetworkStackConfigCommandHandler : IRequestHandler<CreateNetw
{
NetworkStackConfigId = networkStackConfig.Id,
NetworkStackName = networkStackConfig.NetworkStackName,
NetworkStackCode = networkStackConfig.NetworkStackCode,
RanId = networkStackConfig.RanId,
Description = networkStackConfig.Description,
IsActive = networkStackConfig.IsActive,
@ -130,8 +154,8 @@ public class CreateNetworkStackConfigCommandHandler : IRequestHandler<CreateNetw
StackCoreIMSBindings = bindingResponseItems
};
_logger.LogInformation("网络栈配置创建成功,配置ID: {NetworkStackConfigId}, 网络栈名称: {NetworkStackName}, 绑定关系数量: {BindingCount}",
networkStackConfig.Id, networkStackConfig.NetworkStackName, bindingResponseItems.Count);
_logger.LogInformation("网络栈配置创建成功,配置ID: {NetworkStackConfigId}, 网络栈名称: {NetworkStackName}, 网络栈编码: {NetworkStackCode}, 绑定关系数量: {BindingCount}",
networkStackConfig.Id, networkStackConfig.NetworkStackName, networkStackConfig.NetworkStackCode, bindingResponseItems.Count);
return OperationResult<CreateNetworkStackConfigResponse>.CreateSuccess(response);
}
catch (Exception ex)
@ -140,4 +164,45 @@ public class CreateNetworkStackConfigCommandHandler : IRequestHandler<CreateNetw
return OperationResult<CreateNetworkStackConfigResponse>.CreateFailure($"创建网络栈配置时发生错误: {ex.Message}");
}
}
/// <summary>
/// 生成网络栈编码
/// </summary>
private async Task<string> GenerateNetworkStackCodeAsync(CancellationToken cancellationToken)
{
// 获取当前网络栈配置总数
var networkStackCount = await _networkStackConfigRepository.GetNetworkStackConfigCountAsync(cancellationToken);
var nextNumber = networkStackCount + 1;
// 计算需要的位数,确保至少3位数
var digitCount = CalculateRequiredDigits(nextNumber);
// 格式化序号,动态补0,确保从000开始
var formattedNumber = nextNumber.ToString($"D{digitCount}");
// 获取当前时间(毫秒级精度)
var currentTime = DateTime.UtcNow;
var timeStamp = currentTime.ToString("yyyyMMdd-HHmmss-fff");
// 生成网络栈编码格式:NSC-YYYYMMDD-HHMMSS-FFF-000, NSC-YYYYMMDD-HHMMSS-FFF-001 等
var networkStackCode = $"NSC-{timeStamp}-{formattedNumber}";
_logger.LogDebug("生成网络栈编码: {NetworkStackCode}, 网络栈配置总数: {NetworkStackCount}, 位数: {DigitCount}, 时间戳: {TimeStamp}",
networkStackCode, networkStackCount, digitCount, timeStamp);
return networkStackCode;
}
/// <summary>
/// 计算需要的位数
/// </summary>
private int CalculateRequiredDigits(int number)
{
if (number <= 0) return 3; // 从000开始,至少3位数
// 计算位数:确保至少3位数,从000开始
// 1-999用3位,1000-9999用4位,10000-99999用5位,以此类推
var calculatedDigits = (int)Math.Floor(Math.Log10(number)) + 1;
return Math.Max(calculatedDigits, 3); // 确保至少3位数
}
}

5
src/X1.Application/Features/NetworkStackConfigs/Commands/CreateNetworkStackConfig/CreateNetworkStackConfigResponse.cs

@ -15,6 +15,11 @@ public class CreateNetworkStackConfigResponse
/// </summary>
public string NetworkStackName { get; set; } = null!;
/// <summary>
/// 网络栈编码
/// </summary>
public string NetworkStackCode { get; set; } = null!;
/// <summary>
/// RAN配置ID(外键,可为空)
/// </summary>

2
src/X1.Domain/Common/OperationResult.cs

@ -48,7 +48,7 @@ public sealed record OperationResult<T>(
/// </summary>
/// <param name="successMessage">成功消息</param>
/// <returns>成功结果</returns>
public static OperationResult<T> CreateSuccess(string successMessage)
public static OperationResult<T> CreateSuccessWithMessage(string successMessage)
{
return new OperationResult<T>(successMessage, null, default);
}

9
src/X1.Domain/Entities/NetworkProfile/NetworkStackConfig.cs

@ -17,6 +17,13 @@ public class NetworkStackConfig : AuditableEntity
[MaxLength(100)]
public string NetworkStackName { get; private set; } = null!;
/// <summary>
/// 网络栈编码
/// </summary>
[Required]
[MaxLength(50)]
public string NetworkStackCode { get; private set; } = null!;
/// <summary>
/// RAN配置ID(外键,可为空)
/// </summary>
@ -44,6 +51,7 @@ public class NetworkStackConfig : AuditableEntity
/// </summary>
public static NetworkStackConfig Create(
string networkStackName,
string networkStackCode,
string createdBy,
string? ranId = null,
string? description = null,
@ -53,6 +61,7 @@ public class NetworkStackConfig : AuditableEntity
{
Id = Guid.NewGuid().ToString(),
NetworkStackName = networkStackName,
NetworkStackCode = networkStackCode,
RanId = string.IsNullOrWhiteSpace(ranId)?null:ranId,
Description = description,
IsActive = isActive,

10
src/X1.Domain/Repositories/NetworkProfile/INetworkStackConfigRepository.cs

@ -48,6 +48,16 @@ public interface INetworkStackConfigRepository : IBaseRepository<NetworkStackCon
/// </summary>
Task<bool> NameExistsAsync(string networkStackName, CancellationToken cancellationToken = default);
/// <summary>
/// 检查网络栈编码是否存在
/// </summary>
Task<bool> CodeExistsAsync(string networkStackCode, CancellationToken cancellationToken = default);
/// <summary>
/// 获取网络栈配置总数
/// </summary>
Task<int> GetNetworkStackConfigCountAsync(CancellationToken cancellationToken = default);
/// <summary>
/// 搜索网络栈配置
/// </summary>

2
src/X1.Infrastructure/Configurations/NetworkProfile/NetworkStackConfigConfiguration.cs

@ -13,12 +13,14 @@ public class NetworkStackConfigConfiguration : IEntityTypeConfiguration<NetworkS
// 配置索引
builder.HasIndex(nsc => nsc.NetworkStackName).IsUnique().HasDatabaseName("IX_NetworkStackConfigs_NetworkStackName");
builder.HasIndex(nsc => nsc.NetworkStackCode).IsUnique().HasDatabaseName("IX_NetworkStackConfigs_NetworkStackCode");
builder.HasIndex(nsc => nsc.RanId).HasDatabaseName("IX_NetworkStackConfigs_RanId");
builder.HasIndex(nsc => nsc.IsActive).HasDatabaseName("IX_NetworkStackConfigs_IsActive");
// 配置属性
builder.Property(nsc => nsc.Id).HasComment("配置ID");
builder.Property(nsc => nsc.NetworkStackName).IsRequired().HasMaxLength(100).HasComment("网络栈名称");
builder.Property(nsc => nsc.NetworkStackCode).IsRequired().HasMaxLength(50).HasComment("网络栈编码");
builder.Property(nsc => nsc.RanId).HasMaxLength(50).HasComment("RAN配置ID");
builder.Property(nsc => nsc.Description).HasMaxLength(500).HasComment("描述");
builder.Property(nsc => nsc.IsActive).IsRequired().HasComment("是否激活");

923
src/X1.Infrastructure/Migrations/20250729142128_AddNetworkCodeToNetworkStackConfig.Designer.cs

@ -0,0 +1,923 @@
// <auto-generated />
using System;
using CellularManagement.Infrastructure.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace X1.Infrastructure.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20250729142128_AddNetworkCodeToNetworkStackConfig")]
partial class AddNetworkCodeToNetworkStackConfig
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("CellularManagement.Domain.Entities.AppRole", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("角色ID,主键");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text")
.HasComment("并发控制戳");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("Description")
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("角色描述");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("character varying(256)")
.HasComment("角色名称");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("character varying(256)")
.HasComment("标准化角色名称(大写)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique()
.HasDatabaseName("IX_Roles_Name");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex");
b.ToTable("Roles", null, t =>
{
t.HasComment("角色表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.AppUser", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("用户ID,主键");
b.Property<int>("AccessFailedCount")
.HasColumnType("integer")
.HasComment("登录失败次数");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text")
.HasComment("并发控制戳");
b.Property<DateTime>("CreatedTime")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("character varying(256)")
.HasComment("电子邮箱");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean")
.HasComment("邮箱是否已验证");
b.Property<bool>("IsActive")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true)
.HasComment("用户状态(true: 启用, false: 禁用)");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false)
.HasComment("是否已删除");
b.Property<DateTime?>("LastLoginTime")
.HasColumnType("timestamp with time zone")
.HasComment("最后登录时间");
b.Property<bool>("LockoutEnabled")
.HasColumnType("boolean")
.HasComment("是否启用账户锁定");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("timestamp with time zone")
.HasComment("账户锁定结束时间");
b.Property<DateTime?>("ModifiedTime")
.HasColumnType("timestamp with time zone")
.HasComment("修改时间");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)")
.HasComment("标准化电子邮箱(大写)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)")
.HasComment("标准化账号(大写)");
b.Property<string>("PasswordHash")
.HasColumnType("text")
.HasComment("密码哈希值");
b.Property<string>("PhoneNumber")
.IsRequired()
.HasColumnType("text")
.HasComment("电话号码");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("boolean")
.HasComment("电话号码是否已验证");
b.Property<string>("RealName")
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("用户名");
b.Property<string>("SecurityStamp")
.HasColumnType("text")
.HasComment("安全戳,用于并发控制");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("boolean")
.HasComment("是否启用双因素认证");
b.Property<string>("UserName")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("character varying(256)")
.HasComment("账号");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique()
.HasDatabaseName("IX_Users_Email");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex");
b.HasIndex("PhoneNumber")
.IsUnique()
.HasDatabaseName("IX_Users_PhoneNumber");
b.HasIndex("UserName")
.IsUnique()
.HasDatabaseName("IX_Users_UserName");
b.ToTable("Users", null, t =>
{
t.HasComment("用户表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.Device.CellularDevice", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("设备ID");
b.Property<int>("AgentPort")
.HasColumnType("integer")
.HasComment("Agent端口");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("设备描述");
b.Property<string>("DeviceCode")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("设备编码");
b.Property<string>("IpAddress")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("character varying(45)")
.HasComment("IP地址");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<bool>("IsEnabled")
.HasColumnType("boolean")
.HasComment("是否启用");
b.Property<bool>("IsRunning")
.HasColumnType("boolean")
.HasComment("设备状态(启动/未启动)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("设备名称");
b.Property<string>("SerialNumber")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("序列号");
b.Property<DateTime?>("UpdatedAt")
.IsRequired()
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("DeviceCode")
.IsUnique()
.HasDatabaseName("IX_CellularDevices_DeviceCode");
b.HasIndex("SerialNumber")
.IsUnique()
.HasDatabaseName("IX_CellularDevices_SerialNumber");
b.ToTable("CellularDevices", null, t =>
{
t.HasComment("蜂窝设备表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.Device.ProtocolVersion", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("版本ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("版本描述");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<bool>("IsEnabled")
.HasColumnType("boolean")
.HasComment("是否启用");
b.Property<string>("MinimumSupportedVersion")
.HasMaxLength(20)
.HasColumnType("character varying(20)")
.HasComment("最低支持版本");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("版本名称");
b.Property<DateTime?>("ReleaseDate")
.HasColumnType("timestamp with time zone")
.HasComment("发布日期");
b.Property<string>("SerialNumber")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("设备序列号");
b.Property<DateTime?>("UpdatedAt")
.IsRequired()
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.HasColumnType("text");
b.Property<string>("Version")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("character varying(20)")
.HasComment("版本号");
b.HasKey("Id");
b.HasIndex("SerialNumber")
.HasDatabaseName("IX_ProtocolVersions_SerialNumber");
b.HasIndex("Version")
.HasDatabaseName("IX_ProtocolVersions_Version");
b.ToTable("ProtocolVersions", null, t =>
{
t.HasComment("协议版本表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.Logging.LoginLog", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("日志ID");
b.Property<string>("Browser")
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("浏览器信息");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("FailureReason")
.HasMaxLength(200)
.HasColumnType("character varying(200)")
.HasComment("失败原因");
b.Property<string>("IpAddress")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("登录IP");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<bool>("IsSuccess")
.HasColumnType("boolean")
.HasComment("登录状态(成功/失败)");
b.Property<string>("Location")
.HasMaxLength(200)
.HasColumnType("character varying(200)")
.HasComment("登录位置");
b.Property<string>("LoginSource")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<DateTime>("LoginTime")
.HasColumnType("timestamp with time zone")
.HasComment("登录时间");
b.Property<string>("LoginType")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("OperatingSystem")
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("操作系统信息");
b.Property<string>("SessionId")
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("UserAgent")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("设备信息");
b.Property<string>("UserId")
.IsRequired()
.HasMaxLength(450)
.HasColumnType("character varying(450)")
.HasComment("用户ID");
b.HasKey("Id");
b.HasIndex("IpAddress")
.HasDatabaseName("IX_LoginLogs_IpAddress");
b.HasIndex("LoginTime")
.HasDatabaseName("IX_LoginLogs_LoginTime");
b.HasIndex("UserId")
.HasDatabaseName("IX_LoginLogs_UserId");
b.HasIndex("UserId", "LoginTime")
.HasDatabaseName("IX_LoginLogs_UserId_LoginTime");
b.ToTable("LoginLogs", null, t =>
{
t.HasComment("用户登录日志表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.NetworkProfile.CoreNetworkConfig", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("配置ID");
b.Property<string>("ConfigContent")
.IsRequired()
.HasColumnType("text")
.HasComment("配置内容(JSON格式)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("配置描述");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<bool>("IsDisabled")
.HasColumnType("boolean")
.HasComment("是否禁用");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("配置名称");
b.Property<DateTime?>("UpdatedAt")
.IsRequired()
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Name")
.HasDatabaseName("IX_CoreNetworkConfigs_Name");
b.ToTable("CoreNetworkConfigs", null, t =>
{
t.HasComment("核心网配置表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.NetworkProfile.IMS_Configuration", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("配置ID");
b.Property<string>("ConfigContent")
.IsRequired()
.HasColumnType("text")
.HasComment("配置内容(JSON格式)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("配置描述");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<bool>("IsDisabled")
.HasColumnType("boolean")
.HasComment("是否禁用");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("配置名称");
b.Property<DateTime?>("UpdatedAt")
.IsRequired()
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Name")
.HasDatabaseName("IX_IMS_Configurations_Name");
b.ToTable("IMS_Configurations", null, t =>
{
t.HasComment("IMS配置表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.NetworkProfile.NetworkStackConfig", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("配置ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("描述");
b.Property<bool>("IsActive")
.HasColumnType("boolean")
.HasComment("是否激活");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("NetworkCode")
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("NetworkStackName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("网络栈名称");
b.Property<string>("RanId")
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("RAN配置ID");
b.Property<DateTime?>("UpdatedAt")
.IsRequired()
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("IsActive")
.HasDatabaseName("IX_NetworkStackConfigs_IsActive");
b.HasIndex("NetworkStackName")
.IsUnique()
.HasDatabaseName("IX_NetworkStackConfigs_NetworkStackName");
b.HasIndex("RanId")
.HasDatabaseName("IX_NetworkStackConfigs_RanId");
b.ToTable("NetworkStackConfigs", null, t =>
{
t.HasComment("网络栈配置表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.NetworkProfile.RAN_Configuration", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("配置ID");
b.Property<string>("ConfigContent")
.IsRequired()
.HasColumnType("text")
.HasComment("配置内容(JSON格式)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("配置描述");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<bool>("IsDisabled")
.HasColumnType("boolean")
.HasComment("是否禁用");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("配置名称");
b.Property<DateTime?>("UpdatedAt")
.IsRequired()
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Name")
.HasDatabaseName("IX_RAN_Configurations_Name");
b.ToTable("RAN_Configurations", null, t =>
{
t.HasComment("RAN配置表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.NetworkProfile.Stack_CoreIMS_Binding", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("绑定关系ID");
b.Property<string>("CnId")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("核心网配置ID");
b.Property<string>("ImsId")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("IMS配置ID");
b.Property<int>("Index")
.HasColumnType("integer")
.HasComment("索引");
b.Property<string>("NetworkStackConfigId")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("网络栈配置ID");
b.HasKey("Id");
b.HasIndex("CnId")
.HasDatabaseName("IX_Stack_CoreIMS_Bindings_CnId");
b.HasIndex("ImsId")
.HasDatabaseName("IX_Stack_CoreIMS_Bindings_ImsId");
b.HasIndex("NetworkStackConfigId")
.HasDatabaseName("IX_Stack_CoreIMS_Bindings_NetworkStackConfigId");
b.HasIndex("NetworkStackConfigId", "Index")
.IsUnique()
.HasDatabaseName("IX_Stack_CoreIMS_Bindings_NetworkStackConfigId_Index");
b.ToTable("Stack_CoreIMS_Bindings", null, t =>
{
t.HasComment("栈与核心网/IMS绑定关系表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.Permission", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Description")
.HasMaxLength(200)
.HasColumnType("character varying(200)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.HasKey("Id");
b.ToTable("Permissions", (string)null);
});
modelBuilder.Entity("CellularManagement.Domain.Entities.RolePermission", b =>
{
b.Property<string>("RoleId")
.HasColumnType("text");
b.Property<string>("PermissionId")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("RoleId", "PermissionId");
b.HasIndex("PermissionId");
b.ToTable("RolePermissions", (string)null);
});
modelBuilder.Entity("CellularManagement.Domain.Entities.UserRole", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("RoleId")
.HasColumnType("text");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("UserRoles", null, t =>
{
t.HasComment("用户角色关系表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.Device.ProtocolVersion", b =>
{
b.HasOne("CellularManagement.Domain.Entities.Device.CellularDevice", null)
.WithMany("ProtocolVersions")
.HasForeignKey("SerialNumber")
.HasPrincipalKey("SerialNumber")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("CellularManagement.Domain.Entities.Logging.LoginLog", b =>
{
b.HasOne("CellularManagement.Domain.Entities.AppUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
});
modelBuilder.Entity("CellularManagement.Domain.Entities.NetworkProfile.NetworkStackConfig", b =>
{
b.HasOne("CellularManagement.Domain.Entities.NetworkProfile.RAN_Configuration", null)
.WithMany()
.HasForeignKey("RanId")
.OnDelete(DeleteBehavior.SetNull);
});
modelBuilder.Entity("CellularManagement.Domain.Entities.NetworkProfile.Stack_CoreIMS_Binding", b =>
{
b.HasOne("CellularManagement.Domain.Entities.NetworkProfile.CoreNetworkConfig", "CoreNetworkConfig")
.WithMany()
.HasForeignKey("CnId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("CellularManagement.Domain.Entities.NetworkProfile.IMS_Configuration", "IMSConfiguration")
.WithMany()
.HasForeignKey("ImsId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("CellularManagement.Domain.Entities.NetworkProfile.NetworkStackConfig", "NetworkStackConfig")
.WithMany("StackCoreIMSBindings")
.HasForeignKey("NetworkStackConfigId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("CoreNetworkConfig");
b.Navigation("IMSConfiguration");
b.Navigation("NetworkStackConfig");
});
modelBuilder.Entity("CellularManagement.Domain.Entities.RolePermission", b =>
{
b.HasOne("CellularManagement.Domain.Entities.Permission", "Permission")
.WithMany("RolePermissions")
.HasForeignKey("PermissionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("CellularManagement.Domain.Entities.AppRole", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Permission");
b.Navigation("Role");
});
modelBuilder.Entity("CellularManagement.Domain.Entities.UserRole", b =>
{
b.HasOne("CellularManagement.Domain.Entities.AppRole", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("CellularManagement.Domain.Entities.AppUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Role");
b.Navigation("User");
});
modelBuilder.Entity("CellularManagement.Domain.Entities.Device.CellularDevice", b =>
{
b.Navigation("ProtocolVersions");
});
modelBuilder.Entity("CellularManagement.Domain.Entities.NetworkProfile.NetworkStackConfig", b =>
{
b.Navigation("StackCoreIMSBindings");
});
modelBuilder.Entity("CellularManagement.Domain.Entities.Permission", b =>
{
b.Navigation("RolePermissions");
});
#pragma warning restore 612, 618
}
}
}

52
src/X1.Infrastructure/Migrations/20250729142128_AddNetworkCodeToNetworkStackConfig.cs

@ -0,0 +1,52 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace X1.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class AddNetworkCodeToNetworkStackConfig : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "NetworkCode",
table: "NetworkStackConfigs",
type: "character varying(50)",
maxLength: 50,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "DeviceCode",
table: "CellularDevices",
type: "character varying(50)",
maxLength: 50,
nullable: false,
defaultValue: "",
comment: "设备编码");
migrationBuilder.CreateIndex(
name: "IX_CellularDevices_DeviceCode",
table: "CellularDevices",
column: "DeviceCode",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_CellularDevices_DeviceCode",
table: "CellularDevices");
migrationBuilder.DropColumn(
name: "NetworkCode",
table: "NetworkStackConfigs");
migrationBuilder.DropColumn(
name: "DeviceCode",
table: "CellularDevices");
}
}
}

929
src/X1.Infrastructure/Migrations/20250729144236_AddNetworkStackCode.Designer.cs

@ -0,0 +1,929 @@
// <auto-generated />
using System;
using CellularManagement.Infrastructure.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace X1.Infrastructure.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20250729144236_AddNetworkStackCode")]
partial class AddNetworkStackCode
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("CellularManagement.Domain.Entities.AppRole", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("角色ID,主键");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text")
.HasComment("并发控制戳");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("Description")
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("角色描述");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("character varying(256)")
.HasComment("角色名称");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("character varying(256)")
.HasComment("标准化角色名称(大写)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique()
.HasDatabaseName("IX_Roles_Name");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex");
b.ToTable("Roles", null, t =>
{
t.HasComment("角色表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.AppUser", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("用户ID,主键");
b.Property<int>("AccessFailedCount")
.HasColumnType("integer")
.HasComment("登录失败次数");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text")
.HasComment("并发控制戳");
b.Property<DateTime>("CreatedTime")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("character varying(256)")
.HasComment("电子邮箱");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean")
.HasComment("邮箱是否已验证");
b.Property<bool>("IsActive")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true)
.HasComment("用户状态(true: 启用, false: 禁用)");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false)
.HasComment("是否已删除");
b.Property<DateTime?>("LastLoginTime")
.HasColumnType("timestamp with time zone")
.HasComment("最后登录时间");
b.Property<bool>("LockoutEnabled")
.HasColumnType("boolean")
.HasComment("是否启用账户锁定");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("timestamp with time zone")
.HasComment("账户锁定结束时间");
b.Property<DateTime?>("ModifiedTime")
.HasColumnType("timestamp with time zone")
.HasComment("修改时间");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)")
.HasComment("标准化电子邮箱(大写)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)")
.HasComment("标准化账号(大写)");
b.Property<string>("PasswordHash")
.HasColumnType("text")
.HasComment("密码哈希值");
b.Property<string>("PhoneNumber")
.IsRequired()
.HasColumnType("text")
.HasComment("电话号码");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("boolean")
.HasComment("电话号码是否已验证");
b.Property<string>("RealName")
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("用户名");
b.Property<string>("SecurityStamp")
.HasColumnType("text")
.HasComment("安全戳,用于并发控制");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("boolean")
.HasComment("是否启用双因素认证");
b.Property<string>("UserName")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("character varying(256)")
.HasComment("账号");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique()
.HasDatabaseName("IX_Users_Email");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex");
b.HasIndex("PhoneNumber")
.IsUnique()
.HasDatabaseName("IX_Users_PhoneNumber");
b.HasIndex("UserName")
.IsUnique()
.HasDatabaseName("IX_Users_UserName");
b.ToTable("Users", null, t =>
{
t.HasComment("用户表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.Device.CellularDevice", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("设备ID");
b.Property<int>("AgentPort")
.HasColumnType("integer")
.HasComment("Agent端口");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("设备描述");
b.Property<string>("DeviceCode")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("设备编码");
b.Property<string>("IpAddress")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("character varying(45)")
.HasComment("IP地址");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<bool>("IsEnabled")
.HasColumnType("boolean")
.HasComment("是否启用");
b.Property<bool>("IsRunning")
.HasColumnType("boolean")
.HasComment("设备状态(启动/未启动)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("设备名称");
b.Property<string>("SerialNumber")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("序列号");
b.Property<DateTime?>("UpdatedAt")
.IsRequired()
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("DeviceCode")
.IsUnique()
.HasDatabaseName("IX_CellularDevices_DeviceCode");
b.HasIndex("SerialNumber")
.IsUnique()
.HasDatabaseName("IX_CellularDevices_SerialNumber");
b.ToTable("CellularDevices", null, t =>
{
t.HasComment("蜂窝设备表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.Device.ProtocolVersion", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("版本ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("版本描述");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<bool>("IsEnabled")
.HasColumnType("boolean")
.HasComment("是否启用");
b.Property<string>("MinimumSupportedVersion")
.HasMaxLength(20)
.HasColumnType("character varying(20)")
.HasComment("最低支持版本");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("版本名称");
b.Property<DateTime?>("ReleaseDate")
.HasColumnType("timestamp with time zone")
.HasComment("发布日期");
b.Property<string>("SerialNumber")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("设备序列号");
b.Property<DateTime?>("UpdatedAt")
.IsRequired()
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.HasColumnType("text");
b.Property<string>("Version")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("character varying(20)")
.HasComment("版本号");
b.HasKey("Id");
b.HasIndex("SerialNumber")
.HasDatabaseName("IX_ProtocolVersions_SerialNumber");
b.HasIndex("Version")
.HasDatabaseName("IX_ProtocolVersions_Version");
b.ToTable("ProtocolVersions", null, t =>
{
t.HasComment("协议版本表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.Logging.LoginLog", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("日志ID");
b.Property<string>("Browser")
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("浏览器信息");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("FailureReason")
.HasMaxLength(200)
.HasColumnType("character varying(200)")
.HasComment("失败原因");
b.Property<string>("IpAddress")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("登录IP");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<bool>("IsSuccess")
.HasColumnType("boolean")
.HasComment("登录状态(成功/失败)");
b.Property<string>("Location")
.HasMaxLength(200)
.HasColumnType("character varying(200)")
.HasComment("登录位置");
b.Property<string>("LoginSource")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<DateTime>("LoginTime")
.HasColumnType("timestamp with time zone")
.HasComment("登录时间");
b.Property<string>("LoginType")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("OperatingSystem")
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("操作系统信息");
b.Property<string>("SessionId")
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("UserAgent")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("设备信息");
b.Property<string>("UserId")
.IsRequired()
.HasMaxLength(450)
.HasColumnType("character varying(450)")
.HasComment("用户ID");
b.HasKey("Id");
b.HasIndex("IpAddress")
.HasDatabaseName("IX_LoginLogs_IpAddress");
b.HasIndex("LoginTime")
.HasDatabaseName("IX_LoginLogs_LoginTime");
b.HasIndex("UserId")
.HasDatabaseName("IX_LoginLogs_UserId");
b.HasIndex("UserId", "LoginTime")
.HasDatabaseName("IX_LoginLogs_UserId_LoginTime");
b.ToTable("LoginLogs", null, t =>
{
t.HasComment("用户登录日志表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.NetworkProfile.CoreNetworkConfig", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("配置ID");
b.Property<string>("ConfigContent")
.IsRequired()
.HasColumnType("text")
.HasComment("配置内容(JSON格式)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("配置描述");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<bool>("IsDisabled")
.HasColumnType("boolean")
.HasComment("是否禁用");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("配置名称");
b.Property<DateTime?>("UpdatedAt")
.IsRequired()
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Name")
.HasDatabaseName("IX_CoreNetworkConfigs_Name");
b.ToTable("CoreNetworkConfigs", null, t =>
{
t.HasComment("核心网配置表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.NetworkProfile.IMS_Configuration", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("配置ID");
b.Property<string>("ConfigContent")
.IsRequired()
.HasColumnType("text")
.HasComment("配置内容(JSON格式)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("配置描述");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<bool>("IsDisabled")
.HasColumnType("boolean")
.HasComment("是否禁用");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("配置名称");
b.Property<DateTime?>("UpdatedAt")
.IsRequired()
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Name")
.HasDatabaseName("IX_IMS_Configurations_Name");
b.ToTable("IMS_Configurations", null, t =>
{
t.HasComment("IMS配置表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.NetworkProfile.NetworkStackConfig", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("配置ID");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("描述");
b.Property<bool>("IsActive")
.HasColumnType("boolean")
.HasComment("是否激活");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("NetworkStackCode")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("网络栈编码");
b.Property<string>("NetworkStackName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("网络栈名称");
b.Property<string>("RanId")
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("RAN配置ID");
b.Property<DateTime?>("UpdatedAt")
.IsRequired()
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("IsActive")
.HasDatabaseName("IX_NetworkStackConfigs_IsActive");
b.HasIndex("NetworkStackCode")
.IsUnique()
.HasDatabaseName("IX_NetworkStackConfigs_NetworkStackCode");
b.HasIndex("NetworkStackName")
.IsUnique()
.HasDatabaseName("IX_NetworkStackConfigs_NetworkStackName");
b.HasIndex("RanId")
.HasDatabaseName("IX_NetworkStackConfigs_RanId");
b.ToTable("NetworkStackConfigs", null, t =>
{
t.HasComment("网络栈配置表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.NetworkProfile.RAN_Configuration", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("配置ID");
b.Property<string>("ConfigContent")
.IsRequired()
.HasColumnType("text")
.HasComment("配置内容(JSON格式)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间");
b.Property<string>("CreatedBy")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Description")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("character varying(500)")
.HasComment("配置描述");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<bool>("IsDisabled")
.HasColumnType("boolean")
.HasComment("是否禁用");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasComment("配置名称");
b.Property<DateTime?>("UpdatedAt")
.IsRequired()
.HasColumnType("timestamp with time zone")
.HasComment("更新时间");
b.Property<string>("UpdatedBy")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Name")
.HasDatabaseName("IX_RAN_Configurations_Name");
b.ToTable("RAN_Configurations", null, t =>
{
t.HasComment("RAN配置表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.NetworkProfile.Stack_CoreIMS_Binding", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasComment("绑定关系ID");
b.Property<string>("CnId")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("核心网配置ID");
b.Property<string>("ImsId")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("IMS配置ID");
b.Property<int>("Index")
.HasColumnType("integer")
.HasComment("索引");
b.Property<string>("NetworkStackConfigId")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("网络栈配置ID");
b.HasKey("Id");
b.HasIndex("CnId")
.HasDatabaseName("IX_Stack_CoreIMS_Bindings_CnId");
b.HasIndex("ImsId")
.HasDatabaseName("IX_Stack_CoreIMS_Bindings_ImsId");
b.HasIndex("NetworkStackConfigId")
.HasDatabaseName("IX_Stack_CoreIMS_Bindings_NetworkStackConfigId");
b.HasIndex("NetworkStackConfigId", "Index")
.IsUnique()
.HasDatabaseName("IX_Stack_CoreIMS_Bindings_NetworkStackConfigId_Index");
b.ToTable("Stack_CoreIMS_Bindings", null, t =>
{
t.HasComment("栈与核心网/IMS绑定关系表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.Permission", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Description")
.HasMaxLength(200)
.HasColumnType("character varying(200)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.HasKey("Id");
b.ToTable("Permissions", (string)null);
});
modelBuilder.Entity("CellularManagement.Domain.Entities.RolePermission", b =>
{
b.Property<string>("RoleId")
.HasColumnType("text");
b.Property<string>("PermissionId")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("RoleId", "PermissionId");
b.HasIndex("PermissionId");
b.ToTable("RolePermissions", (string)null);
});
modelBuilder.Entity("CellularManagement.Domain.Entities.UserRole", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("RoleId")
.HasColumnType("text");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("UserRoles", null, t =>
{
t.HasComment("用户角色关系表");
});
});
modelBuilder.Entity("CellularManagement.Domain.Entities.Device.ProtocolVersion", b =>
{
b.HasOne("CellularManagement.Domain.Entities.Device.CellularDevice", null)
.WithMany("ProtocolVersions")
.HasForeignKey("SerialNumber")
.HasPrincipalKey("SerialNumber")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("CellularManagement.Domain.Entities.Logging.LoginLog", b =>
{
b.HasOne("CellularManagement.Domain.Entities.AppUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
});
modelBuilder.Entity("CellularManagement.Domain.Entities.NetworkProfile.NetworkStackConfig", b =>
{
b.HasOne("CellularManagement.Domain.Entities.NetworkProfile.RAN_Configuration", null)
.WithMany()
.HasForeignKey("RanId")
.OnDelete(DeleteBehavior.SetNull);
});
modelBuilder.Entity("CellularManagement.Domain.Entities.NetworkProfile.Stack_CoreIMS_Binding", b =>
{
b.HasOne("CellularManagement.Domain.Entities.NetworkProfile.CoreNetworkConfig", "CoreNetworkConfig")
.WithMany()
.HasForeignKey("CnId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("CellularManagement.Domain.Entities.NetworkProfile.IMS_Configuration", "IMSConfiguration")
.WithMany()
.HasForeignKey("ImsId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("CellularManagement.Domain.Entities.NetworkProfile.NetworkStackConfig", "NetworkStackConfig")
.WithMany("StackCoreIMSBindings")
.HasForeignKey("NetworkStackConfigId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("CoreNetworkConfig");
b.Navigation("IMSConfiguration");
b.Navigation("NetworkStackConfig");
});
modelBuilder.Entity("CellularManagement.Domain.Entities.RolePermission", b =>
{
b.HasOne("CellularManagement.Domain.Entities.Permission", "Permission")
.WithMany("RolePermissions")
.HasForeignKey("PermissionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("CellularManagement.Domain.Entities.AppRole", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Permission");
b.Navigation("Role");
});
modelBuilder.Entity("CellularManagement.Domain.Entities.UserRole", b =>
{
b.HasOne("CellularManagement.Domain.Entities.AppRole", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("CellularManagement.Domain.Entities.AppUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Role");
b.Navigation("User");
});
modelBuilder.Entity("CellularManagement.Domain.Entities.Device.CellularDevice", b =>
{
b.Navigation("ProtocolVersions");
});
modelBuilder.Entity("CellularManagement.Domain.Entities.NetworkProfile.NetworkStackConfig", b =>
{
b.Navigation("StackCoreIMSBindings");
});
modelBuilder.Entity("CellularManagement.Domain.Entities.Permission", b =>
{
b.Navigation("RolePermissions");
});
#pragma warning restore 612, 618
}
}
}

76
src/X1.Infrastructure/Migrations/20250729144236_AddNetworkStackCode.cs

@ -0,0 +1,76 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace X1.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class AddNetworkStackCode : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "NetworkCode",
table: "NetworkStackConfigs");
migrationBuilder.AddColumn<string>(
name: "NetworkStackCode",
table: "NetworkStackConfigs",
type: "character varying(50)",
maxLength: 50,
nullable: true,
comment: "网络栈编码");
// 为现有数据生成编码
migrationBuilder.Sql(@"
WITH numbered_configs AS (
SELECT
""Id"",
ROW_NUMBER() OVER (ORDER BY ""CreatedAt"") as row_num,
to_char(""CreatedAt"", 'YYYYMMDD-HH24MISS-MS') as time_stamp
FROM ""NetworkStackConfigs""
WHERE ""NetworkStackCode"" IS NULL
)
UPDATE ""NetworkStackConfigs""
SET ""NetworkStackCode"" = 'NSC-' || nc.time_stamp || '-' || LPAD(nc.row_num::text, 3, '0')
FROM numbered_configs nc
WHERE ""NetworkStackConfigs"".""Id"" = nc.""Id"";
");
// 设置字段为非空
migrationBuilder.AlterColumn<string>(
name: "NetworkStackCode",
table: "NetworkStackConfigs",
type: "character varying(50)",
maxLength: 50,
nullable: false,
comment: "网络栈编码");
migrationBuilder.CreateIndex(
name: "IX_NetworkStackConfigs_NetworkStackCode",
table: "NetworkStackConfigs",
column: "NetworkStackCode",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_NetworkStackConfigs_NetworkStackCode",
table: "NetworkStackConfigs");
migrationBuilder.DropColumn(
name: "NetworkStackCode",
table: "NetworkStackConfigs");
migrationBuilder.AddColumn<string>(
name: "NetworkCode",
table: "NetworkStackConfigs",
type: "character varying(50)",
maxLength: 50,
nullable: true);
}
}
}

20
src/X1.Infrastructure/Migrations/AppDbContextModelSnapshot.cs

@ -224,6 +224,12 @@ namespace X1.Infrastructure.Migrations
.HasColumnType("character varying(500)")
.HasComment("设备描述");
b.Property<string>("DeviceCode")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("设备编码");
b.Property<string>("IpAddress")
.IsRequired()
.HasMaxLength(45)
@ -263,6 +269,10 @@ namespace X1.Infrastructure.Migrations
b.HasKey("Id");
b.HasIndex("DeviceCode")
.IsUnique()
.HasDatabaseName("IX_CellularDevices_DeviceCode");
b.HasIndex("SerialNumber")
.IsUnique()
.HasDatabaseName("IX_CellularDevices_SerialNumber");
@ -583,6 +593,12 @@ namespace X1.Infrastructure.Migrations
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("NetworkStackCode")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasComment("网络栈编码");
b.Property<string>("NetworkStackName")
.IsRequired()
.HasMaxLength(100)
@ -607,6 +623,10 @@ namespace X1.Infrastructure.Migrations
b.HasIndex("IsActive")
.HasDatabaseName("IX_NetworkStackConfigs_IsActive");
b.HasIndex("NetworkStackCode")
.IsUnique()
.HasDatabaseName("IX_NetworkStackConfigs_NetworkStackCode");
b.HasIndex("NetworkStackName")
.IsUnique()
.HasDatabaseName("IX_NetworkStackConfigs_NetworkStackName");

16
src/X1.Infrastructure/Repositories/NetworkProfile/NetworkStackConfigRepository.cs

@ -154,6 +154,22 @@ public class NetworkStackConfigRepository : BaseRepository<NetworkStackConfig>,
return await QueryRepository.AnyAsync(nsc => nsc.NetworkStackName == networkStackName, cancellationToken: cancellationToken);
}
/// <summary>
/// 检查网络栈编码是否存在
/// </summary>
public async Task<bool> CodeExistsAsync(string networkStackCode, CancellationToken cancellationToken = default)
{
return await QueryRepository.AnyAsync(nsc => nsc.NetworkStackCode == networkStackCode, cancellationToken: cancellationToken);
}
/// <summary>
/// 获取网络栈配置总数
/// </summary>
public async Task<int> GetNetworkStackConfigCountAsync(CancellationToken cancellationToken = default)
{
return await QueryRepository.CountAsync(nsc => true, cancellationToken: cancellationToken);
}
/// <summary>
/// 根据ID获取网络栈配置(包含绑定关系)
/// </summary>

4
src/X1.WebAPI/Properties/launchSettings.json

@ -24,8 +24,8 @@
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7268;http://localhost:5000;https://192.168.2.142:7268;http://192.168.2.142:5000",
//"applicationUrl": "https://localhost:7268;http://localhost:5000",
//"applicationUrl": "https://localhost:7268;http://localhost:5000;https://192.168.2.142:7268;http://192.168.2.142:5000",
"applicationUrl": "https://localhost:7268;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}

3
src/X1.WebUI/src/services/networkStackConfigService.ts

@ -6,6 +6,7 @@ import { API_PATHS } from '@/constants/api';
export interface NetworkStackConfig {
networkStackConfigId: string;
networkStackName: string;
networkStackCode: string;
ranId?: string;
description?: string;
isActive: boolean;
@ -66,6 +67,7 @@ export interface CreateStackCoreIMSBindingItem {
export interface CreateNetworkStackConfigResponse {
networkStackConfigId: string;
networkStackName: string;
networkStackCode: string;
ranId?: string;
description?: string;
isActive: boolean;
@ -94,6 +96,7 @@ export interface UpdateStackCoreIMSBindingItem {
export interface UpdateNetworkStackConfigResponse {
networkStackConfigId: string;
networkStackName: string;
networkStackCode: string;
ranId?: string;
description?: string;
isActive: boolean;

Loading…
Cancel
Save