评教系统

This commit is contained in:
2026-07-25 18:41:53 +08:00 Unverified
parent 15a34a306c
commit 376bc0d0a1
12 changed files with 6667 additions and 487 deletions
@@ -62,6 +62,10 @@ public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
public DbSet<CourseSubstitution> CourseSubstitutions => Set<CourseSubstitution>();
public DbSet<WarningRule> WarningRules => Set<WarningRule>();
public DbSet<WarningRecord> WarningRecords => Set<WarningRecord>();
public DbSet<EvaluationSetup> EvaluationSetups => Set<EvaluationSetup>();
public DbSet<EvaluationDimension> EvaluationDimensions => Set<EvaluationDimension>();
public DbSet<EvaluationRecord> EvaluationRecords => Set<EvaluationRecord>();
public DbSet<EvaluationScore> EvaluationScores => Set<EvaluationScore>();
public DbSet<Notification> Notifications => Set<Notification>();
public DbSet<StudentStatusChange> StudentStatusChanges =>
Set<StudentStatusChange>();
@@ -731,6 +735,43 @@ public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
.HasForeignKey(x => x.StudentId).OnDelete(DeleteBehavior.Restrict);
});
// ── Evaluation ──
builder.Entity<EvaluationSetup>(entity =>
{
entity.Property(x => x.Name).HasMaxLength(120);
entity.HasIndex(x => new { x.AcademicTermId, x.Status });
entity.HasOne(x => x.AcademicTerm).WithMany()
.HasForeignKey(x => x.AcademicTermId).OnDelete(DeleteBehavior.Restrict);
});
builder.Entity<EvaluationDimension>(entity =>
{
entity.Property(x => x.Name).HasMaxLength(60);
entity.HasIndex(x => new { x.EvaluationSetupId, x.SortOrder });
entity.HasOne(x => x.EvaluationSetup).WithMany(x => x.Dimensions)
.HasForeignKey(x => x.EvaluationSetupId).OnDelete(DeleteBehavior.Cascade);
});
builder.Entity<EvaluationRecord>(entity =>
{
entity.HasIndex(x => new { x.EvaluationSetupId, x.StudentId, x.TeachingTaskId }).IsUnique();
entity.HasOne(x => x.EvaluationSetup).WithMany(x => x.Records)
.HasForeignKey(x => x.EvaluationSetupId).OnDelete(DeleteBehavior.Restrict);
entity.HasOne(x => x.Student).WithMany()
.HasForeignKey(x => x.StudentId).OnDelete(DeleteBehavior.Restrict);
entity.HasOne(x => x.TeachingTask).WithMany()
.HasForeignKey(x => x.TeachingTaskId).OnDelete(DeleteBehavior.Restrict);
});
builder.Entity<EvaluationScore>(entity =>
{
entity.HasKey(x => new { x.EvaluationRecordId, x.EvaluationDimensionId });
entity.HasOne(x => x.EvaluationRecord).WithMany(x => x.Scores)
.HasForeignKey(x => x.EvaluationRecordId).OnDelete(DeleteBehavior.Cascade);
entity.HasOne(x => x.EvaluationDimension).WithMany(x => x.Scores)
.HasForeignKey(x => x.EvaluationDimensionId).OnDelete(DeleteBehavior.Restrict);
});
builder.Entity<CourseSubstitution>(entity =>
{
entity.Property(x => x.Reason).HasMaxLength(500);
@@ -290,6 +290,14 @@ public sealed class DevelopmentSqliteMigrator(
AcademicWarningsMigration,
warningRulesExist ? [] : AcademicWarningStatements,
cancellationToken);
var evaluationSetupsExist = await db.Database
.SqlQueryRaw<int>("SELECT COUNT(*) AS \"Value\" FROM sqlite_master WHERE type = 'table' AND name = 'EvaluationSetups'")
.AnyAsync(value => value > 0, cancellationToken);
await ApplyMigrationAsync(
TeachingEvaluationMigration,
evaluationSetupsExist ? [] : TeachingEvaluationStatements,
cancellationToken);
}
private async Task ApplyMigrationAsync(
@@ -1630,4 +1638,17 @@ public sealed class DevelopmentSqliteMigrator(
"""ALTER TABLE "WarningRules" ADD COLUMN "CheckMinute" INTEGER NOT NULL DEFAULT 0;""",
"""ALTER TABLE "WarningRules" ADD COLUMN "LastCheckAt" TEXT NULL;"""
];
private const string TeachingEvaluationMigration = "TeachingEvaluation";
private static readonly string[] TeachingEvaluationStatements =
[
"""CREATE TABLE "EvaluationSetups" ("Id" TEXT NOT NULL, "CreatedAt" TEXT NOT NULL, "UpdatedAt" TEXT NOT NULL, "AcademicTermId" TEXT NOT NULL, "Name" TEXT NOT NULL, "Status" INTEGER NOT NULL, "StartsAt" TEXT NULL, "EndsAt" TEXT NULL, CONSTRAINT "PK_EvaluationSetups" PRIMARY KEY ("Id"), CONSTRAINT "FK_EvaluationSetups_AcademicTerms_AcademicTermId" FOREIGN KEY ("AcademicTermId") REFERENCES "AcademicTerms" ("Id") ON DELETE RESTRICT);""",
"""CREATE INDEX "IX_EvaluationSetups_AcademicTermId_Status" ON "EvaluationSetups" ("AcademicTermId", "Status");""",
"""CREATE TABLE "EvaluationDimensions" ("Id" TEXT NOT NULL, "CreatedAt" TEXT NOT NULL, "UpdatedAt" TEXT NOT NULL, "EvaluationSetupId" TEXT NOT NULL, "Name" TEXT NOT NULL, "MaxScore" INTEGER NOT NULL, "SortOrder" INTEGER NOT NULL, CONSTRAINT "PK_EvaluationDimensions" PRIMARY KEY ("Id"), CONSTRAINT "FK_EvaluationDimensions_EvaluationSetups_EvaluationSetupId" FOREIGN KEY ("EvaluationSetupId") REFERENCES "EvaluationSetups" ("Id") ON DELETE CASCADE);""",
"""CREATE INDEX "IX_EvaluationDimensions_EvaluationSetupId_SortOrder" ON "EvaluationDimensions" ("EvaluationSetupId", "SortOrder");""",
"""CREATE TABLE "EvaluationRecords" ("Id" TEXT NOT NULL, "CreatedAt" TEXT NOT NULL, "UpdatedAt" TEXT NOT NULL, "EvaluationSetupId" TEXT NOT NULL, "StudentId" TEXT NOT NULL, "TeachingTaskId" TEXT NOT NULL, "SubmittedAt" TEXT NULL, CONSTRAINT "PK_EvaluationRecords" PRIMARY KEY ("Id"), CONSTRAINT "FK_EvaluationRecords_EvaluationSetups_EvaluationSetupId" FOREIGN KEY ("EvaluationSetupId") REFERENCES "EvaluationSetups" ("Id") ON DELETE RESTRICT, CONSTRAINT "FK_EvaluationRecords_Students_StudentId" FOREIGN KEY ("StudentId") REFERENCES "Students" ("Id") ON DELETE RESTRICT, CONSTRAINT "FK_EvaluationRecords_TeachingTasks_TeachingTaskId" FOREIGN KEY ("TeachingTaskId") REFERENCES "TeachingTasks" ("Id") ON DELETE RESTRICT);""",
"""CREATE UNIQUE INDEX "IX_EvaluationRecords_SetupId_StudentId_TaskId" ON "EvaluationRecords" ("EvaluationSetupId", "StudentId", "TeachingTaskId");""",
"""CREATE TABLE "EvaluationScores" ("EvaluationRecordId" TEXT NOT NULL, "EvaluationDimensionId" TEXT NOT NULL, "Score" INTEGER NOT NULL, CONSTRAINT "PK_EvaluationScores" PRIMARY KEY ("EvaluationRecordId", "EvaluationDimensionId"), CONSTRAINT "FK_EvaluationScores_EvaluationRecords_EvaluationRecordId" FOREIGN KEY ("EvaluationRecordId") REFERENCES "EvaluationRecords" ("Id") ON DELETE CASCADE, CONSTRAINT "FK_EvaluationScores_EvaluationDimensions_EvaluationDimensionId" FOREIGN KEY ("EvaluationDimensionId") REFERENCES "EvaluationDimensions" ("Id") ON DELETE RESTRICT);""",
];
}
@@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
{
/// <inheritdoc />
public partial class TeachingEvaluation : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}
File diff suppressed because it is too large Load Diff