多角色账号按 All > College > Class > Self 自动取最高权限。

学院管理员限制在所属学院。
辅导员通过稳定账号 ID 绑定行政班,避免重名串班。
教师只能访问本人档案、授课课程和所授课学生。
学生只能访问本人档案及所在班级课程。
教师/学生角色会自动校验并绑定工号或学号档案。
超级管理员可在用户页面调整角色、学院、工号/学号,并预览生效后的数据范围。
This commit is contained in:
2026-07-24 14:54:30 +08:00 Unverified
parent 0b463fa4f2
commit bcc4d33bd5
26 changed files with 2333 additions and 88 deletions
@@ -10,6 +10,7 @@ public sealed class DevelopmentSqliteMigrator(
private const string CurriculumPlansMigration = "20260724_02_curriculum_plans";
private const string TeachingTasksMigration = "20260724_03_teaching_tasks";
private const string SchedulesMigration = "20260724_04_schedules";
private const string ClassCounselorMigration = "20260724_05_class_counselor";
public async Task MigrateAsync(CancellationToken cancellationToken = default)
{
@@ -43,6 +44,20 @@ public sealed class DevelopmentSqliteMigrator(
SchedulesMigration,
SchedulesStatements,
cancellationToken);
var counselorColumnExists = await db.Database
.SqlQueryRaw<int>(
"""
SELECT COUNT(*) AS "Value"
FROM pragma_table_info('AdministrativeClasses')
WHERE name = 'CounselorUserId'
""")
.AnyAsync(value => value > 0, cancellationToken);
await ApplyMigrationAsync(
ClassCounselorMigration,
counselorColumnExists
? ClassCounselorStatements.Skip(1)
: ClassCounselorStatements,
cancellationToken);
}
private async Task ApplyMigrationAsync(
@@ -399,4 +414,16 @@ public sealed class DevelopmentSqliteMigrator(
ON "ScheduleEntries" ("ClassroomId");
"""
];
private static readonly string[] ClassCounselorStatements =
[
"""
ALTER TABLE "AdministrativeClasses"
ADD COLUMN "CounselorUserId" TEXT NULL;
""",
"""
CREATE INDEX IF NOT EXISTS "IX_AdministrativeClasses_CounselorUserId"
ON "AdministrativeClasses" ("CounselorUserId");
"""
];
}