选课
This commit is contained in:
@@ -10,6 +10,7 @@ public sealed class DatabaseInitializer(
|
||||
RoleManager<ApplicationRole> roleManager,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
DevelopmentSqliteMigrator sqliteMigrator,
|
||||
DevelopmentDemoDataSeeder developmentDemoDataSeeder,
|
||||
IConfiguration configuration,
|
||||
IHostEnvironment environment,
|
||||
ILogger<DatabaseInitializer> logger)
|
||||
@@ -479,6 +480,7 @@ public sealed class DatabaseInitializer(
|
||||
await SeedDevelopmentCourseSelectionAsync();
|
||||
await SeedDevelopmentGradesAsync();
|
||||
await SeedDevelopmentExamsAsync();
|
||||
await developmentDemoDataSeeder.SeedAsync();
|
||||
}
|
||||
|
||||
private async Task SeedDevelopmentCourseSelectionAsync()
|
||||
|
||||
@@ -0,0 +1,620 @@
|
||||
using Jiaowu.Api.Domain.Academic;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Jiaowu.Api.Infrastructure.Persistence;
|
||||
|
||||
public sealed class DevelopmentDemoDataSeeder(
|
||||
AppDbContext db,
|
||||
ILogger<DevelopmentDemoDataSeeder> logger)
|
||||
{
|
||||
private const int Grade = 2026;
|
||||
private const int ClassesPerMajor = 2;
|
||||
private const int StudentsPerClass = 35;
|
||||
private const int TeachersPerCollege = 8;
|
||||
|
||||
public async Task SeedAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var campus = await db.Campuses
|
||||
.OrderBy(x => x.Code == "MAIN" ? 0 : 1)
|
||||
.ThenBy(x => x.Code)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
if (campus is null)
|
||||
{
|
||||
campus = new Campus
|
||||
{
|
||||
Code = "MAIN",
|
||||
Name = "主校区",
|
||||
Address = "大学路 1 号"
|
||||
};
|
||||
db.Campuses.Add(campus);
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
await SeedCollegesAsync(campus.Id, cancellationToken);
|
||||
await SeedMajorsAsync(cancellationToken);
|
||||
await SeedClassesAsync(cancellationToken);
|
||||
await SeedTeachersAsync(cancellationToken);
|
||||
await SeedStudentsAsync(cancellationToken);
|
||||
await SeedCoursesAsync(cancellationToken);
|
||||
await SeedTeacherCourseApplicationsAsync(cancellationToken);
|
||||
await LogSummaryAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private async Task SeedCollegesAsync(Guid campusId, CancellationToken cancellationToken)
|
||||
{
|
||||
var existingCodes = (await db.Colleges
|
||||
.Select(x => x.Code)
|
||||
.ToListAsync(cancellationToken))
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
var additions = CollegeDefinitions
|
||||
.Where(x => !existingCodes.Contains(x.Code))
|
||||
.Select((x, index) => new College
|
||||
{
|
||||
Code = x.Code,
|
||||
Name = x.Name,
|
||||
ShortName = x.ShortName,
|
||||
CampusId = campusId,
|
||||
SortOrder = (index + 1) * 10
|
||||
})
|
||||
.ToList();
|
||||
if (additions.Count == 0) return;
|
||||
db.Colleges.AddRange(additions);
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private async Task SeedMajorsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var colleges = await db.Colleges
|
||||
.ToDictionaryAsync(x => x.Code, StringComparer.OrdinalIgnoreCase, cancellationToken);
|
||||
var existingCodes = (await db.Majors
|
||||
.Select(x => x.Code)
|
||||
.ToListAsync(cancellationToken))
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
var additions = new List<Major>();
|
||||
foreach (var collegeDefinition in CollegeDefinitions)
|
||||
{
|
||||
if (!colleges.TryGetValue(collegeDefinition.Code, out var college)) continue;
|
||||
for (var index = 0; index < collegeDefinition.Majors.Count; index++)
|
||||
{
|
||||
var definition = collegeDefinition.Majors[index];
|
||||
if (existingCodes.Contains(definition.Code)) continue;
|
||||
additions.Add(new Major
|
||||
{
|
||||
Code = definition.Code,
|
||||
Name = definition.Name,
|
||||
CollegeId = college.Id,
|
||||
DegreeType = definition.DegreeType,
|
||||
SchoolingYears = definition.SchoolingYears,
|
||||
SortOrder = (index + 1) * 10
|
||||
});
|
||||
}
|
||||
}
|
||||
if (additions.Count == 0) return;
|
||||
db.Majors.AddRange(additions);
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private async Task SeedClassesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var targetMajorCodes = CollegeDefinitions
|
||||
.SelectMany(x => x.Majors)
|
||||
.Select(x => x.Code)
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
var majors = await db.Majors
|
||||
.Where(x => targetMajorCodes.Contains(x.Code))
|
||||
.OrderBy(x => x.Code)
|
||||
.ToListAsync(cancellationToken);
|
||||
var existingClasses = await db.AdministrativeClasses
|
||||
.Where(x => x.Grade == Grade && targetMajorCodes.Contains(x.Major!.Code))
|
||||
.OrderBy(x => x.Code)
|
||||
.ToListAsync(cancellationToken);
|
||||
var existingCodes = (await db.AdministrativeClasses
|
||||
.Select(x => x.Code)
|
||||
.ToListAsync(cancellationToken))
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
var additions = new List<AdministrativeClass>();
|
||||
foreach (var major in majors)
|
||||
{
|
||||
var currentCount = existingClasses.Count(x => x.MajorId == major.Id);
|
||||
for (var section = currentCount + 1; section <= ClassesPerMajor; section++)
|
||||
{
|
||||
var code = CreateAvailableCode(
|
||||
$"{major.Code}-{Grade}-{section:D2}",
|
||||
existingCodes);
|
||||
additions.Add(new AdministrativeClass
|
||||
{
|
||||
Code = code,
|
||||
Name = $"{major.Name}{Grade}级{section}班",
|
||||
MajorId = major.Id,
|
||||
Grade = Grade,
|
||||
CounselorName = $"{CounselorSurnames[(section + major.Code.Length) % CounselorSurnames.Length]}老师",
|
||||
SortOrder = section * 10
|
||||
});
|
||||
}
|
||||
}
|
||||
if (additions.Count == 0) return;
|
||||
db.AdministrativeClasses.AddRange(additions);
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private async Task SeedTeachersAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var collegeCodes = CollegeDefinitions
|
||||
.Select(x => x.Code)
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
var colleges = await db.Colleges
|
||||
.Where(x => collegeCodes.Contains(x.Code))
|
||||
.OrderBy(x => x.Code)
|
||||
.ToListAsync(cancellationToken);
|
||||
var existingTeachers = await db.Teachers
|
||||
.Where(x => colleges.Select(c => c.Id).Contains(x.CollegeId))
|
||||
.ToListAsync(cancellationToken);
|
||||
var existingNumbers = (await db.Teachers
|
||||
.Select(x => x.TeacherNumber)
|
||||
.ToListAsync(cancellationToken))
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
var additions = new List<Teacher>();
|
||||
for (var collegeIndex = 0; collegeIndex < colleges.Count; collegeIndex++)
|
||||
{
|
||||
var college = colleges[collegeIndex];
|
||||
var currentCount = existingTeachers.Count(x => x.CollegeId == college.Id);
|
||||
for (var position = currentCount + 1; position <= TeachersPerCollege; position++)
|
||||
{
|
||||
var teacherNumber = CreateAvailableCode(
|
||||
$"T26{collegeIndex + 1:D2}{position:D3}",
|
||||
existingNumbers);
|
||||
additions.Add(new Teacher
|
||||
{
|
||||
TeacherNumber = teacherNumber,
|
||||
Name = BuildPersonName(collegeIndex, position),
|
||||
Gender = position % 2 == 0 ? Gender.Female : Gender.Male,
|
||||
CollegeId = college.Id,
|
||||
Title = TeacherTitles[(position - 1) % TeacherTitles.Length],
|
||||
Status = TeacherStatus.Active,
|
||||
HireDate = new DateOnly(2012 + position, 7, 1),
|
||||
Email = $"{teacherNumber.ToLowerInvariant()}@example.edu.cn",
|
||||
Notes = "Development 环境批量测试教师。"
|
||||
});
|
||||
}
|
||||
}
|
||||
if (additions.Count == 0) return;
|
||||
db.Teachers.AddRange(additions);
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private async Task SeedStudentsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var targetMajorCodes = CollegeDefinitions
|
||||
.SelectMany(x => x.Majors)
|
||||
.Select(x => x.Code)
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
var classes = await db.AdministrativeClasses
|
||||
.Where(x => x.Grade == Grade && targetMajorCodes.Contains(x.Major!.Code))
|
||||
.OrderBy(x => x.Code)
|
||||
.ToListAsync(cancellationToken);
|
||||
var classIds = classes.Select(x => x.Id).ToHashSet();
|
||||
var existingStudents = await db.Students
|
||||
.Where(x => classIds.Contains(x.AdministrativeClassId))
|
||||
.ToListAsync(cancellationToken);
|
||||
var existingNumbers = (await db.Students
|
||||
.Select(x => x.StudentNumber)
|
||||
.ToListAsync(cancellationToken))
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
var additions = new List<Student>();
|
||||
for (var classIndex = 0; classIndex < classes.Count; classIndex++)
|
||||
{
|
||||
var administrativeClass = classes[classIndex];
|
||||
var existingCount = existingStudents.Count(x =>
|
||||
x.AdministrativeClassId == administrativeClass.Id);
|
||||
var candidate = 1;
|
||||
while (existingCount + additions.Count(x =>
|
||||
x.AdministrativeClassId == administrativeClass.Id) < StudentsPerClass)
|
||||
{
|
||||
var studentNumber = $"{Grade}{classIndex + 1:D3}{candidate:D3}";
|
||||
candidate++;
|
||||
if (!existingNumbers.Add(studentNumber)) continue;
|
||||
additions.Add(new Student
|
||||
{
|
||||
StudentNumber = studentNumber,
|
||||
Name = BuildPersonName(classIndex, candidate + 5),
|
||||
Gender = candidate % 2 == 0 ? Gender.Male : Gender.Female,
|
||||
AdministrativeClassId = administrativeClass.Id,
|
||||
EnrollmentYear = Grade,
|
||||
EnrollmentDate = new DateOnly(Grade, 9, 7),
|
||||
DateOfBirth = new DateOnly(2007 + candidate % 2, candidate % 12 + 1,
|
||||
candidate % 27 + 1),
|
||||
Status = StudentStatus.Active,
|
||||
Email = $"{studentNumber}@student.example.edu.cn",
|
||||
Notes = "Development 环境批量测试学生。"
|
||||
});
|
||||
}
|
||||
}
|
||||
if (additions.Count == 0) return;
|
||||
db.Students.AddRange(additions);
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private async Task SeedCoursesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var colleges = await db.Colleges
|
||||
.ToDictionaryAsync(x => x.Code, StringComparer.OrdinalIgnoreCase, cancellationToken);
|
||||
var categories = await db.CourseCategories
|
||||
.ToDictionaryAsync(x => x.Code, StringComparer.OrdinalIgnoreCase, cancellationToken);
|
||||
var existingCodes = (await db.Courses
|
||||
.Select(x => x.Code)
|
||||
.ToListAsync(cancellationToken))
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
var additions = new List<Course>();
|
||||
|
||||
foreach (var definition in PublicCourseDefinitions)
|
||||
{
|
||||
if (existingCodes.Contains(definition.Code) ||
|
||||
!colleges.TryGetValue(definition.CollegeCode, out var college) ||
|
||||
!categories.TryGetValue(definition.CategoryCode, out var category))
|
||||
continue;
|
||||
additions.Add(new Course
|
||||
{
|
||||
Code = definition.Code,
|
||||
Name = definition.Name,
|
||||
CollegeId = college.Id,
|
||||
CourseCategoryId = category.Id,
|
||||
Credits = definition.Credits,
|
||||
TotalHours = definition.TotalHours,
|
||||
LectureHours = definition.LectureHours,
|
||||
PracticeHours = definition.TotalHours - definition.LectureHours,
|
||||
Nature = definition.Nature,
|
||||
AssessmentMethod = definition.AssessmentMethod,
|
||||
Description = "Development 环境公共课程测试数据。"
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var collegeDefinition in CollegeDefinitions)
|
||||
{
|
||||
if (!colleges.TryGetValue(collegeDefinition.Code, out var college)) continue;
|
||||
for (var index = 0; index < collegeDefinition.ProfessionalCourses.Count; index++)
|
||||
{
|
||||
var code = $"{collegeDefinition.Code}D{index + 1:D2}";
|
||||
if (existingCodes.Contains(code)) continue;
|
||||
var nature = index switch
|
||||
{
|
||||
< 4 => CourseNature.MajorRequired,
|
||||
< 6 => CourseNature.MajorElective,
|
||||
_ => CourseNature.Practice
|
||||
};
|
||||
var categoryCode = nature == CourseNature.Practice ? "PRACTICE" : "MAJOR";
|
||||
additions.Add(new Course
|
||||
{
|
||||
Code = code,
|
||||
Name = collegeDefinition.ProfessionalCourses[index],
|
||||
CollegeId = college.Id,
|
||||
CourseCategoryId = categories[categoryCode].Id,
|
||||
Credits = nature switch
|
||||
{
|
||||
CourseNature.MajorRequired => index % 2 == 0 ? 3m : 3.5m,
|
||||
_ => 2m
|
||||
},
|
||||
TotalHours = nature switch
|
||||
{
|
||||
CourseNature.MajorRequired => index % 2 == 0 ? 48 : 56,
|
||||
CourseNature.MajorElective => 32,
|
||||
_ => 48
|
||||
},
|
||||
LectureHours = nature == CourseNature.Practice ? 8 :
|
||||
nature == CourseNature.MajorElective ? 24 :
|
||||
index % 2 == 0 ? 40 : 48,
|
||||
PracticeHours = nature == CourseNature.Practice ? 40 :
|
||||
nature == CourseNature.MajorElective ? 8 : 8,
|
||||
Nature = nature,
|
||||
AssessmentMethod = nature == CourseNature.Practice
|
||||
? AssessmentMethod.Assessment
|
||||
: AssessmentMethod.Examination,
|
||||
Description = $"由{collegeDefinition.Name}开设的专业课程测试数据。"
|
||||
});
|
||||
}
|
||||
}
|
||||
if (additions.Count == 0) return;
|
||||
db.Courses.AddRange(additions);
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private async Task SeedTeacherCourseApplicationsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var term = await db.AcademicTerms
|
||||
.OrderByDescending(x => x.IsCurrent)
|
||||
.ThenByDescending(x => x.StartDate)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
if (term is null) return;
|
||||
|
||||
var collegeCodes = CollegeDefinitions
|
||||
.Select(x => x.Code)
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
var colleges = await db.Colleges
|
||||
.Where(x => collegeCodes.Contains(x.Code))
|
||||
.OrderBy(x => x.Code)
|
||||
.ToListAsync(cancellationToken);
|
||||
var collegeIds = colleges.Select(x => x.Id).ToHashSet();
|
||||
var teachers = await db.Teachers
|
||||
.Where(x => collegeIds.Contains(x.CollegeId) && x.Status == TeacherStatus.Active)
|
||||
.OrderBy(x => x.TeacherNumber)
|
||||
.ToListAsync(cancellationToken);
|
||||
var courses = await db.Courses
|
||||
.Where(x => collegeIds.Contains(x.CollegeId))
|
||||
.OrderBy(x => x.Code)
|
||||
.ToListAsync(cancellationToken);
|
||||
var publicCourses = courses
|
||||
.Where(x => x.Nature is CourseNature.GeneralRequired or CourseNature.GeneralElective)
|
||||
.ToList();
|
||||
if (publicCourses.Count == 0) return;
|
||||
|
||||
var existing = (await db.TeacherCourseApplications
|
||||
.Where(x => x.AcademicTermId == term.Id)
|
||||
.Select(x => new { x.TeacherId, x.CourseId })
|
||||
.ToListAsync(cancellationToken))
|
||||
.Select(x => (x.TeacherId, x.CourseId))
|
||||
.ToHashSet();
|
||||
var additions = new List<TeacherCourseApplication>();
|
||||
for (var teacherIndex = 0; teacherIndex < teachers.Count; teacherIndex++)
|
||||
{
|
||||
var teacher = teachers[teacherIndex];
|
||||
var professionalCourses = courses
|
||||
.Where(x => x.CollegeId == teacher.CollegeId &&
|
||||
x.Nature is CourseNature.MajorRequired or
|
||||
CourseNature.MajorElective or CourseNature.Practice)
|
||||
.Take(4);
|
||||
var selectedPublicCourses = Enumerable.Range(0, 2)
|
||||
.Select(offset => publicCourses[(teacherIndex + offset) % publicCourses.Count]);
|
||||
foreach (var course in professionalCourses
|
||||
.Concat(selectedPublicCourses)
|
||||
.DistinctBy(x => x.Id))
|
||||
{
|
||||
if (!existing.Add((teacher.Id, course.Id))) continue;
|
||||
additions.Add(new TeacherCourseApplication
|
||||
{
|
||||
AcademicTermId = term.Id,
|
||||
TeacherId = teacher.Id,
|
||||
CourseId = course.Id,
|
||||
Status = TeacherCourseApplicationStatus.Approved,
|
||||
Statement = "Development 环境批量生成的授课意向。",
|
||||
ReviewComment = "测试数据自动审核通过。",
|
||||
SubmittedAt = DateTime.UtcNow.AddDays(-7),
|
||||
ReviewedAt = DateTime.UtcNow.AddDays(-6)
|
||||
});
|
||||
}
|
||||
}
|
||||
if (additions.Count == 0) return;
|
||||
db.TeacherCourseApplications.AddRange(additions);
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private async Task LogSummaryAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var courseCounts = await db.Courses
|
||||
.GroupBy(x => x.Nature)
|
||||
.Select(x => new { Nature = x.Key, Count = x.Count() })
|
||||
.ToDictionaryAsync(x => x.Nature, x => x.Count, cancellationToken);
|
||||
logger.LogInformation(
|
||||
"Development 测试数据已就绪:学院/教学单位 {CollegeCount},专业 {MajorCount}," +
|
||||
"行政班 {ClassCount},教师 {TeacherCount},学生 {StudentCount},课程 {CourseCount};" +
|
||||
"公共必修 {GeneralRequiredCount},公共选修 {GeneralElectiveCount}," +
|
||||
"专业必修 {MajorRequiredCount},专业选修 {MajorElectiveCount},实践课程 {PracticeCount};" +
|
||||
"已审核授课资格 {ApplicationCount}。",
|
||||
await db.Colleges.CountAsync(cancellationToken),
|
||||
await db.Majors.CountAsync(cancellationToken),
|
||||
await db.AdministrativeClasses.CountAsync(cancellationToken),
|
||||
await db.Teachers.CountAsync(cancellationToken),
|
||||
await db.Students.CountAsync(cancellationToken),
|
||||
await db.Courses.CountAsync(cancellationToken),
|
||||
courseCounts.GetValueOrDefault(CourseNature.GeneralRequired),
|
||||
courseCounts.GetValueOrDefault(CourseNature.GeneralElective),
|
||||
courseCounts.GetValueOrDefault(CourseNature.MajorRequired),
|
||||
courseCounts.GetValueOrDefault(CourseNature.MajorElective),
|
||||
courseCounts.GetValueOrDefault(CourseNature.Practice),
|
||||
await db.TeacherCourseApplications
|
||||
.CountAsync(x => x.Status == TeacherCourseApplicationStatus.Approved,
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
private static string CreateAvailableCode(string preferredCode, ISet<string> existingCodes)
|
||||
{
|
||||
var candidate = preferredCode;
|
||||
var suffix = 1;
|
||||
while (!existingCodes.Add(candidate))
|
||||
{
|
||||
candidate = $"{preferredCode}-{suffix++}";
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
|
||||
private static string BuildPersonName(int groupIndex, int position)
|
||||
{
|
||||
var surname = Surnames[(groupIndex + position) % Surnames.Length];
|
||||
var givenName = GivenNames[
|
||||
(groupIndex * 7 + position * 3) % GivenNames.Length];
|
||||
return surname + givenName;
|
||||
}
|
||||
|
||||
private static readonly string[] Surnames =
|
||||
["王", "李", "张", "刘", "陈", "杨", "黄", "赵", "吴", "周", "徐", "孙", "马", "朱", "胡", "郭", "何", "高", "林", "罗"];
|
||||
|
||||
private static readonly string[] GivenNames =
|
||||
["明远", "知夏", "嘉树", "雨桐", "思源", "若溪", "景行", "书雅", "子涵", "浩然", "清越", "语晨", "承宇", "欣怡", "博文", "婉宁", "俊逸", "安然", "泽楷", "可心"];
|
||||
|
||||
private static readonly string[] CounselorSurnames =
|
||||
["陈", "林", "周", "王", "李", "张", "刘", "赵"];
|
||||
|
||||
private static readonly string[] TeacherTitles =
|
||||
["教授", "副教授", "讲师", "讲师", "副教授", "实验师", "讲师", "教授"];
|
||||
|
||||
private static readonly CollegeSeed[] CollegeDefinitions =
|
||||
[
|
||||
new("CS", "计算机学院", "计算机学院",
|
||||
[
|
||||
new("080901", "计算机科学与技术", "工学学士"),
|
||||
new("080902", "软件工程", "工学学士"),
|
||||
new("080903", "网络工程", "工学学士"),
|
||||
new("080910T", "数据科学与大数据技术", "工学学士"),
|
||||
new("080717T", "人工智能", "工学学士")
|
||||
],
|
||||
["程序设计基础", "离散数学", "数据结构", "计算机组成原理", "操作系统", "数据库系统原理", "软件工程课程设计", "人工智能项目实践"]),
|
||||
new("EIA", "电子信息与自动化学院", "电子信息学院",
|
||||
[
|
||||
new("080701", "电子信息工程", "工学学士"),
|
||||
new("080703", "通信工程", "工学学士"),
|
||||
new("080801", "自动化", "工学学士"),
|
||||
new("080803T", "机器人工程", "工学学士")
|
||||
],
|
||||
["电路分析", "模拟电子技术", "数字电子技术", "信号与系统", "通信原理", "嵌入式系统", "电子系统设计", "综合电子实训"]),
|
||||
new("ME", "机械与车辆工程学院", "机械学院",
|
||||
[
|
||||
new("080202", "机械设计制造及其自动化", "工学学士"),
|
||||
new("080207", "车辆工程", "工学学士"),
|
||||
new("080205", "工业设计", "工学学士"),
|
||||
new("080213T", "智能制造工程", "工学学士")
|
||||
],
|
||||
["工程制图", "理论力学", "材料力学", "机械原理", "机械设计", "智能制造技术", "机械创新设计", "工程训练"]),
|
||||
new("EE", "电气工程学院", "电气学院",
|
||||
[
|
||||
new("080601", "电气工程及其自动化", "工学学士"),
|
||||
new("080604T", "电气工程与智能控制", "工学学士"),
|
||||
new("080605T", "电机电器智能化", "工学学士")
|
||||
],
|
||||
["电路原理", "电机学", "电力电子技术", "自动控制原理", "电力系统分析", "继电保护", "电气控制实训", "电力系统综合设计"]),
|
||||
new("CIVIL", "土木建筑工程学院", "土建学院",
|
||||
[
|
||||
new("081001", "土木工程", "工学学士"),
|
||||
new("082801", "建筑学", "建筑学学士", 5),
|
||||
new("120103", "工程管理", "管理学学士"),
|
||||
new("081006T", "道路桥梁与渡河工程", "工学学士")
|
||||
],
|
||||
["工程制图与识图", "工程力学", "结构力学", "混凝土结构", "土力学与地基基础", "工程项目管理", "建筑设计基础", "工程测量实习"]),
|
||||
new("ECON", "经济与管理学院", "经管学院",
|
||||
[
|
||||
new("120201K", "工商管理", "管理学学士"),
|
||||
new("120203K", "会计学", "管理学学士"),
|
||||
new("020301K", "金融学", "经济学学士"),
|
||||
new("020401", "国际经济与贸易", "经济学学士"),
|
||||
new("120202", "市场营销", "管理学学士")
|
||||
],
|
||||
["微观经济学", "宏观经济学", "管理学原理", "会计学原理", "统计学", "财务管理", "企业经营沙盘", "商务数据分析实践"]),
|
||||
new("FOREIGN", "外国语学院", "外国语学院",
|
||||
[
|
||||
new("050201", "英语", "文学学士"),
|
||||
new("050207", "日语", "文学学士"),
|
||||
new("050262", "商务英语", "文学学士")
|
||||
],
|
||||
["综合英语", "英语听力", "英语口语", "英语写作", "翻译理论与实践", "跨文化交际", "商务英语实训", "口译实践"]),
|
||||
new("MATH", "数学与统计学院", "数统学院",
|
||||
[
|
||||
new("070101", "数学与应用数学", "理学学士"),
|
||||
new("071201", "统计学", "理学学士"),
|
||||
new("020102", "经济统计学", "经济学学士")
|
||||
],
|
||||
["数学分析", "高等代数", "解析几何", "常微分方程", "实变函数", "数值分析", "数学建模", "统计软件实践"]),
|
||||
new("PHYSICS", "物理与光电工程学院", "物电学院",
|
||||
[
|
||||
new("070201", "物理学", "理学学士"),
|
||||
new("070202", "应用物理学", "理学学士"),
|
||||
new("080705", "光电信息科学与工程", "工学学士")
|
||||
],
|
||||
["力学", "热学", "电磁学", "光学", "量子力学", "固体物理", "近代物理实验", "光电技术综合实验"]),
|
||||
new("CHEM", "化学与环境工程学院", "化环学院",
|
||||
[
|
||||
new("070301", "化学", "理学学士"),
|
||||
new("070302", "应用化学", "理学学士"),
|
||||
new("081301", "化学工程与工艺", "工学学士"),
|
||||
new("082502", "环境工程", "工学学士")
|
||||
],
|
||||
["无机化学", "有机化学", "分析化学", "物理化学", "化工原理", "仪器分析", "基础化学实验", "化工设计实践"]),
|
||||
new("HUMANITIES", "人文与法学院", "人文法学院",
|
||||
[
|
||||
new("050101", "汉语言文学", "文学学士"),
|
||||
new("030101K", "法学", "法学学士"),
|
||||
new("120402", "行政管理", "管理学学士")
|
||||
],
|
||||
["中国古代文学", "中国现当代文学", "现代汉语", "古代汉语", "文学概论", "行政管理学", "新闻写作实训", "社会调查实践"]),
|
||||
new("EDU", "教育科学学院", "教育学院",
|
||||
[
|
||||
new("040101", "教育学", "教育学学士"),
|
||||
new("040107", "小学教育", "教育学学士"),
|
||||
new("040106", "学前教育", "教育学学士")
|
||||
],
|
||||
["教育学原理", "普通心理学", "教育心理学", "课程与教学论", "教育研究方法", "班级管理", "微格教学", "教育见习"]),
|
||||
new("ART", "艺术设计学院", "艺术学院",
|
||||
[
|
||||
new("130502", "视觉传达设计", "艺术学学士"),
|
||||
new("130503", "环境设计", "艺术学学士"),
|
||||
new("130202", "音乐学", "艺术学学士")
|
||||
],
|
||||
["设计素描", "色彩基础", "构成基础", "艺术概论", "数字媒体设计", "品牌视觉设计", "专业采风", "毕业创作实践"]),
|
||||
new("PE", "体育学院", "体育学院",
|
||||
[
|
||||
new("040201", "体育教育", "教育学学士"),
|
||||
new("040203", "社会体育指导与管理", "教育学学士")
|
||||
],
|
||||
["运动解剖学", "运动生理学", "学校体育学", "体育心理学", "运动训练学", "体育社会学", "田径专项训练", "球类专项训练"]),
|
||||
new("LIFE", "生命科学与食品工程学院", "生食学院",
|
||||
[
|
||||
new("071001", "生物科学", "理学学士"),
|
||||
new("071002", "生物技术", "理学学士"),
|
||||
new("082701", "食品科学与工程", "工学学士")
|
||||
],
|
||||
["普通生物学", "生物化学", "细胞生物学", "遗传学", "微生物学", "食品化学", "分子生物学实验", "生物工程综合实践"]),
|
||||
new("MARXISM", "马克思主义学院", "马克思主义学院", [], [])
|
||||
];
|
||||
|
||||
private static readonly PublicCourseSeed[] PublicCourseDefinitions =
|
||||
[
|
||||
new("PUB001", "思想道德与法治", "MARXISM", "MORAL", 3, 48, 48, CourseNature.GeneralRequired),
|
||||
new("PUB002", "中国近现代史纲要", "MARXISM", "MORAL", 3, 48, 48, CourseNature.GeneralRequired),
|
||||
new("PUB003", "马克思主义基本原理", "MARXISM", "MORAL", 3, 48, 48, CourseNature.GeneralRequired),
|
||||
new("PUB004", "毛泽东思想和中国特色社会主义理论体系概论", "MARXISM", "MORAL", 5, 80, 64, CourseNature.GeneralRequired),
|
||||
new("PUB005", "习近平新时代中国特色社会主义思想概论", "MARXISM", "MORAL", 3, 48, 48, CourseNature.GeneralRequired),
|
||||
new("PUB006", "形势与政策", "MARXISM", "MORAL", 2, 32, 32, CourseNature.GeneralRequired, AssessmentMethod.Assessment),
|
||||
new("PUB007", "大学英语 I", "FOREIGN", "ENGLISH", 4, 64, 48, CourseNature.GeneralRequired),
|
||||
new("PUB008", "大学英语 II", "FOREIGN", "ENGLISH", 4, 64, 48, CourseNature.GeneralRequired),
|
||||
new("PUB009", "高等数学 A(上)", "MATH", "BASIC", 5, 80, 80, CourseNature.GeneralRequired),
|
||||
new("PUB010", "高等数学 A(下)", "MATH", "BASIC", 5, 80, 80, CourseNature.GeneralRequired),
|
||||
new("PUB011", "线性代数", "MATH", "BASIC", 3, 48, 48, CourseNature.GeneralRequired),
|
||||
new("PUB012", "概率论与数理统计", "MATH", "BASIC", 3, 48, 48, CourseNature.GeneralRequired),
|
||||
new("PUB013", "大学计算机基础", "CS", "BASIC", 2, 32, 16, CourseNature.GeneralRequired),
|
||||
new("PUB014", "Python 程序设计", "CS", "BASIC", 3, 48, 24, CourseNature.GeneralRequired),
|
||||
new("PUB015", "大学体育 I", "PE", "SPORTS", 1, 32, 4, CourseNature.GeneralRequired, AssessmentMethod.Assessment),
|
||||
new("PUB016", "大学体育 II", "PE", "SPORTS", 1, 32, 4, CourseNature.GeneralRequired, AssessmentMethod.Assessment),
|
||||
new("PUB017", "军事理论", "HUMANITIES", "MILITARY", 2, 36, 32, CourseNature.GeneralRequired, AssessmentMethod.Assessment),
|
||||
new("PUB018", "大学生心理健康教育", "EDU", "BASIC", 2, 32, 24, CourseNature.GeneralRequired, AssessmentMethod.Assessment),
|
||||
new("PUB019", "大学生职业发展与就业指导", "EDU", "BASIC", 2, 32, 24, CourseNature.GeneralRequired, AssessmentMethod.Assessment),
|
||||
new("PUB020", "创新创业基础", "ECON", "INNOVATION", 2, 32, 20, CourseNature.GeneralRequired, AssessmentMethod.Assessment),
|
||||
new("PUB021", "劳动教育", "EDU", "LABOR", 1, 32, 8, CourseNature.GeneralRequired, AssessmentMethod.Assessment),
|
||||
new("PUB022", "国家安全教育", "HUMANITIES", "MORAL", 1, 16, 16, CourseNature.GeneralRequired, AssessmentMethod.Assessment),
|
||||
new("PUB023", "文献检索与学术规范", "HUMANITIES", "BASIC", 1, 16, 12, CourseNature.GeneralRequired, AssessmentMethod.Assessment),
|
||||
new("PUB024", "艺术鉴赏", "ART", "AESTHETIC", 2, 32, 24, CourseNature.GeneralElective, AssessmentMethod.Assessment),
|
||||
new("PUB025", "中国传统文化", "HUMANITIES", "AESTHETIC", 2, 32, 32, CourseNature.GeneralElective, AssessmentMethod.Assessment),
|
||||
new("PUB026", "生态文明导论", "LIFE", "BASIC", 2, 32, 24, CourseNature.GeneralElective, AssessmentMethod.Assessment),
|
||||
new("PUB027", "人工智能导论", "CS", "INNOVATION", 2, 32, 20, CourseNature.GeneralElective, AssessmentMethod.Assessment),
|
||||
new("PUB028", "经济学通识", "ECON", "BASIC", 2, 32, 32, CourseNature.GeneralElective, AssessmentMethod.Assessment)
|
||||
];
|
||||
|
||||
private sealed record CollegeSeed(
|
||||
string Code,
|
||||
string Name,
|
||||
string ShortName,
|
||||
IReadOnlyList<MajorSeed> Majors,
|
||||
IReadOnlyList<string> ProfessionalCourses);
|
||||
|
||||
private sealed record MajorSeed(
|
||||
string Code,
|
||||
string Name,
|
||||
string DegreeType,
|
||||
int SchoolingYears = 4);
|
||||
|
||||
private sealed record PublicCourseSeed(
|
||||
string Code,
|
||||
string Name,
|
||||
string CollegeCode,
|
||||
string CategoryCode,
|
||||
decimal Credits,
|
||||
int TotalHours,
|
||||
int LectureHours,
|
||||
CourseNature Nature,
|
||||
AssessmentMethod AssessmentMethod = AssessmentMethod.Examination);
|
||||
}
|
||||
Reference in New Issue
Block a user