feat: add phase five operations foundation

This commit is contained in:
2026-07-28 09:57:50 +08:00
parent 71793a2de0
commit f22f329d33
39 changed files with 4810 additions and 160 deletions

View File

@@ -1,6 +1,7 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Tiku.Domain.Catalog;
using Tiku.Domain.Content;
using Tiku.Domain.Identity;
using Tiku.Domain.Operations;
using Tiku.Domain.QuestionBanks;
@@ -79,6 +80,206 @@ internal sealed class AuditLogConfiguration : IEntityTypeConfiguration<AuditLog>
}
}
internal sealed class BackendPermissionConfiguration : IEntityTypeConfiguration<BackendPermission>
{
public void Configure(EntityTypeBuilder<BackendPermission> builder)
{
builder.ConfigureEntity("backend_permissions");
builder.ConfigureTimestamps();
builder.Property(entity => entity.Code).HasMaxLength(160);
builder.Property(entity => entity.Name).HasMaxLength(200);
builder.Property(entity => entity.Area).HasSnakeCaseEnum();
builder.Property(entity => entity.Module).HasMaxLength(100);
builder.Property(entity => entity.Description).HasMaxLength(1000);
builder.HasIndex(entity => entity.Code).IsUnique();
builder.HasIndex(entity => new { entity.Area, entity.Module, entity.SortOrder });
}
}
internal sealed class BackendMenuConfiguration : IEntityTypeConfiguration<BackendMenu>
{
public void Configure(EntityTypeBuilder<BackendMenu> builder)
{
builder.ConfigureEntity("backend_menus");
builder.ConfigureTimestamps();
builder.Property(entity => entity.Code).HasMaxLength(160);
builder.Property(entity => entity.ParentCode).HasMaxLength(160);
builder.Property(entity => entity.Title).HasMaxLength(200);
builder.Property(entity => entity.Area).HasSnakeCaseEnum();
builder.Property(entity => entity.Path).HasMaxLength(1024);
builder.Property(entity => entity.Icon).HasMaxLength(100);
builder.Property(entity => entity.PermissionCode).HasMaxLength(160);
builder.HasIndex(entity => entity.Code).IsUnique();
builder.HasIndex(entity => new { entity.Area, entity.ParentCode, entity.SortOrder });
builder.HasOne<BackendPermission>().WithMany()
.HasPrincipalKey(entity => entity.Code)
.HasForeignKey(entity => entity.PermissionCode)
.OnDelete(DeleteBehavior.SetNull);
}
}
internal sealed class TenantBackendRoleConfiguration : IEntityTypeConfiguration<TenantBackendRole>
{
public void Configure(EntityTypeBuilder<TenantBackendRole> builder)
{
builder.ConfigureTenantEntity("tenant_backend_roles");
builder.ConfigureTimestamps();
builder.Property(entity => entity.Code).HasMaxLength(100);
builder.Property(entity => entity.Name).HasMaxLength(200);
builder.Property(entity => entity.Status).HasSnakeCaseEnum();
builder.Property(entity => entity.Description).HasMaxLength(1000);
builder.Property(entity => entity.DataScope).IsJson("{}");
builder.HasIndex(entity => new { entity.TenantId, entity.Code }).IsUnique();
builder.HasIndex(entity => new { entity.TenantId, entity.Status, entity.Code });
}
}
internal sealed class TenantBackendRolePermissionConfiguration : IEntityTypeConfiguration<TenantBackendRolePermission>
{
public void Configure(EntityTypeBuilder<TenantBackendRolePermission> builder)
{
builder.ConfigureEntity("tenant_backend_role_permissions");
builder.Property(entity => entity.PermissionCode).HasMaxLength(160);
builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()");
builder.HasAlternateKey(entity => new { entity.TenantId, entity.Id });
builder.HasIndex(entity => new { entity.TenantId, entity.RoleId, entity.PermissionCode }).IsUnique();
builder.HasOne<TenantBackendRole>().WithMany()
.HasForeignKey(entity => new { entity.TenantId, entity.RoleId })
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
.OnDelete(DeleteBehavior.Cascade);
builder.HasOne<BackendPermission>().WithMany()
.HasPrincipalKey(entity => entity.Code)
.HasForeignKey(entity => entity.PermissionCode)
.OnDelete(DeleteBehavior.Restrict);
}
}
internal sealed class TenantBackendRoleMenuConfiguration : IEntityTypeConfiguration<TenantBackendRoleMenu>
{
public void Configure(EntityTypeBuilder<TenantBackendRoleMenu> builder)
{
builder.ConfigureEntity("tenant_backend_role_menus");
builder.Property(entity => entity.MenuCode).HasMaxLength(160);
builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()");
builder.HasAlternateKey(entity => new { entity.TenantId, entity.Id });
builder.HasIndex(entity => new { entity.TenantId, entity.RoleId, entity.MenuCode }).IsUnique();
builder.HasOne<TenantBackendRole>().WithMany()
.HasForeignKey(entity => new { entity.TenantId, entity.RoleId })
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
.OnDelete(DeleteBehavior.Cascade);
builder.HasOne<BackendMenu>().WithMany()
.HasPrincipalKey(entity => entity.Code)
.HasForeignKey(entity => entity.MenuCode)
.OnDelete(DeleteBehavior.Restrict);
}
}
internal sealed class TenantBackendUserRoleConfiguration : IEntityTypeConfiguration<TenantBackendUserRole>
{
public void Configure(EntityTypeBuilder<TenantBackendUserRole> builder)
{
builder.ConfigureEntity("tenant_backend_user_roles");
builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()");
builder.HasAlternateKey(entity => new { entity.TenantId, entity.Id });
builder.HasIndex(entity => new { entity.TenantId, entity.UserId, entity.RoleId }).IsUnique();
builder.HasOne<TenantBackendRole>().WithMany()
.HasForeignKey(entity => new { entity.TenantId, entity.RoleId })
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
.OnDelete(DeleteBehavior.Cascade);
builder.HasOne<User>().WithMany()
.HasForeignKey(entity => entity.UserId)
.OnDelete(DeleteBehavior.Cascade);
}
}
internal sealed class PlatformBackendRoleConfiguration : IEntityTypeConfiguration<PlatformBackendRole>
{
public void Configure(EntityTypeBuilder<PlatformBackendRole> builder)
{
builder.ConfigureEntity("platform_backend_roles");
builder.ConfigureTimestamps();
builder.Property(entity => entity.Code).HasMaxLength(100);
builder.Property(entity => entity.Name).HasMaxLength(200);
builder.Property(entity => entity.Status).HasSnakeCaseEnum();
builder.Property(entity => entity.Description).HasMaxLength(1000);
builder.HasIndex(entity => entity.Code).IsUnique();
builder.HasIndex(entity => new { entity.Status, entity.Code });
}
}
internal sealed class PlatformBackendRolePermissionConfiguration : IEntityTypeConfiguration<PlatformBackendRolePermission>
{
public void Configure(EntityTypeBuilder<PlatformBackendRolePermission> builder)
{
builder.ConfigureEntity("platform_backend_role_permissions");
builder.Property(entity => entity.PermissionCode).HasMaxLength(160);
builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()");
builder.HasIndex(entity => new { entity.RoleId, entity.PermissionCode }).IsUnique();
builder.HasOne<PlatformBackendRole>().WithMany()
.HasForeignKey(entity => entity.RoleId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasOne<BackendPermission>().WithMany()
.HasPrincipalKey(entity => entity.Code)
.HasForeignKey(entity => entity.PermissionCode)
.OnDelete(DeleteBehavior.Restrict);
}
}
internal sealed class PlatformBackendRoleMenuConfiguration : IEntityTypeConfiguration<PlatformBackendRoleMenu>
{
public void Configure(EntityTypeBuilder<PlatformBackendRoleMenu> builder)
{
builder.ConfigureEntity("platform_backend_role_menus");
builder.Property(entity => entity.MenuCode).HasMaxLength(160);
builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()");
builder.HasIndex(entity => new { entity.RoleId, entity.MenuCode }).IsUnique();
builder.HasOne<PlatformBackendRole>().WithMany()
.HasForeignKey(entity => entity.RoleId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasOne<BackendMenu>().WithMany()
.HasPrincipalKey(entity => entity.Code)
.HasForeignKey(entity => entity.MenuCode)
.OnDelete(DeleteBehavior.Restrict);
}
}
internal sealed class PlatformBackendUserRoleConfiguration : IEntityTypeConfiguration<PlatformBackendUserRole>
{
public void Configure(EntityTypeBuilder<PlatformBackendUserRole> builder)
{
builder.ConfigureEntity("platform_backend_user_roles");
builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()");
builder.HasIndex(entity => new { entity.UserId, entity.RoleId }).IsUnique();
builder.HasOne<PlatformBackendRole>().WithMany()
.HasForeignKey(entity => entity.RoleId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasOne<User>().WithMany()
.HasForeignKey(entity => entity.UserId)
.OnDelete(DeleteBehavior.Cascade);
}
}
internal sealed class BackgroundJobConfiguration : IEntityTypeConfiguration<BackgroundJob>
{
public void Configure(EntityTypeBuilder<BackgroundJob> builder)
{
builder.ConfigureTenantEntity("background_jobs");
builder.ConfigureTimestamps();
builder.Property(entity => entity.JobType).HasMaxLength(100);
builder.Property(entity => entity.Status).HasSnakeCaseEnum();
builder.Property(entity => entity.Payload).IsJson("{}");
builder.Property(entity => entity.LockedBy).HasMaxLength(200);
builder.Property(entity => entity.LastError).HasMaxLength(4000);
builder.Property(entity => entity.Result).IsJson("{}");
builder.HasIndex(entity => new { entity.TenantId, entity.Status, entity.RunAfter, entity.CreatedAt });
builder.HasIndex(entity => new { entity.TenantId, entity.JobType, entity.Status, entity.CreatedAt });
builder.HasOne<ContentAsset>().WithMany()
.HasForeignKey(entity => new { entity.TenantId, entity.OutputAssetId })
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
.OnDelete(DeleteBehavior.SetNull);
}
}
internal sealed class UserNotificationConfiguration : IEntityTypeConfiguration<UserNotification>
{
public void Configure(EntityTypeBuilder<UserNotification> builder)