课程库:保留并验证现有 Excel 导入,支持模板下载、按编码新增/更新、整批校验及事务回滚。
授课资格:学院可直接选择本院教师、学期和课程并分配资格,服务端强制学院数据范围。[后端接口 (line 178)](/E:/jiaowu/src/Jiaowu.Api/Controllers/TeacherCourseApplicationsController.cs:178) · [页面 (line 151)](/E:/jiaowu/web/src/views/TeachingPreferencesView.vue:151) 学生培养方案:新增“我的培养方案”,展示学分进度及已完成、在读、重修中、未通过、待完成、未修读课程,并支持搜索筛选。[学生接口 (line 15)](/E:/jiaowu/src/Jiaowu.Api/Controllers/StudentCurriculumController.cs:15) · [学生页面 (line 88)](/E:/jiaowu/web/src/views/StudentCurriculumView.vue:88)
This commit is contained in:
@@ -175,6 +175,102 @@ public sealed class TeacherCourseApplicationsController(
|
||||
.ToListAsync(cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("assignment-options")]
|
||||
[Authorize(Roles = ReviewRoles)]
|
||||
public async Task<ActionResult> GetAssignmentOptions(
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var teachers = db.Teachers.AsNoTracking()
|
||||
.Where(x => x.Status == TeacherStatus.Active);
|
||||
var collegeId = currentUserDataScope.Current.RestrictedCollegeId;
|
||||
if (collegeId.HasValue)
|
||||
teachers = teachers.Where(x => x.CollegeId == collegeId.Value);
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
Teachers = await teachers
|
||||
.OrderBy(x => x.TeacherNumber)
|
||||
.Select(x => new
|
||||
{
|
||||
x.Id,
|
||||
x.TeacherNumber,
|
||||
x.Name,
|
||||
x.Title,
|
||||
x.CollegeId,
|
||||
CollegeName = x.College!.Name
|
||||
})
|
||||
.ToListAsync(cancellationToken),
|
||||
Courses = await db.Courses.AsNoTracking()
|
||||
.Where(x => x.IsEnabled)
|
||||
.OrderBy(x => x.SortOrder)
|
||||
.ThenBy(x => x.Code)
|
||||
.Select(x => new
|
||||
{
|
||||
x.Id,
|
||||
x.Code,
|
||||
x.Name,
|
||||
x.CollegeId,
|
||||
CollegeName = x.College!.Name,
|
||||
x.Credits,
|
||||
x.Nature
|
||||
})
|
||||
.ToListAsync(cancellationToken)
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost("assign")]
|
||||
[Authorize(Roles = ReviewRoles)]
|
||||
public async Task<ActionResult> Assign(
|
||||
TeacherCourseAssignmentRequest request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (!await db.AcademicTerms.AnyAsync(
|
||||
x => x.Id == request.AcademicTermId && x.IsEnabled,
|
||||
cancellationToken))
|
||||
return ValidationProblem("所选学期不存在或已停用。");
|
||||
if (!await db.Courses.AnyAsync(
|
||||
x => x.Id == request.CourseId && x.IsEnabled,
|
||||
cancellationToken))
|
||||
return ValidationProblem("所选课程不存在或已停用。");
|
||||
|
||||
var teachers = db.Teachers.Where(x =>
|
||||
x.Id == request.TeacherId &&
|
||||
x.Status == TeacherStatus.Active);
|
||||
var collegeId = currentUserDataScope.Current.RestrictedCollegeId;
|
||||
if (collegeId.HasValue)
|
||||
teachers = teachers.Where(x => x.CollegeId == collegeId.Value);
|
||||
if (!await teachers.AnyAsync(cancellationToken))
|
||||
return ValidationProblem("所选教师不存在、不在职或不属于当前学院。");
|
||||
|
||||
var application = await db.TeacherCourseApplications
|
||||
.FirstOrDefaultAsync(x =>
|
||||
x.AcademicTermId == request.AcademicTermId &&
|
||||
x.TeacherId == request.TeacherId &&
|
||||
x.CourseId == request.CourseId,
|
||||
cancellationToken);
|
||||
if (application?.Status == TeacherCourseApplicationStatus.Approved)
|
||||
return ConflictProblem("该教师在所选学期已具备此课程的授课资格。");
|
||||
|
||||
if (application is null)
|
||||
{
|
||||
application = new TeacherCourseApplication
|
||||
{
|
||||
AcademicTermId = request.AcademicTermId,
|
||||
TeacherId = request.TeacherId,
|
||||
CourseId = request.CourseId,
|
||||
SubmittedAt = DateTime.UtcNow
|
||||
};
|
||||
db.TeacherCourseApplications.Add(application);
|
||||
}
|
||||
|
||||
application.Status = TeacherCourseApplicationStatus.Approved;
|
||||
application.ReviewComment = Normalize(request.Comment) ?? "学院直接分配";
|
||||
application.ReviewedAt = DateTime.UtcNow;
|
||||
application.ReviewedByUserId = currentUserDataScope.Current.UserId;
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
return Ok(new { application.Id });
|
||||
}
|
||||
|
||||
[HttpPost("{id:guid}/review")]
|
||||
[Authorize(Roles = ReviewRoles)]
|
||||
public async Task<ActionResult> Review(
|
||||
@@ -262,3 +358,9 @@ public sealed record TeacherCourseApplicationRequest(
|
||||
public sealed record TeacherCourseReviewRequest(
|
||||
TeacherCourseApplicationStatus Status,
|
||||
[MaxLength(500)] string? ReviewComment);
|
||||
|
||||
public sealed record TeacherCourseAssignmentRequest(
|
||||
Guid AcademicTermId,
|
||||
Guid TeacherId,
|
||||
Guid CourseId,
|
||||
[MaxLength(500)] string? Comment);
|
||||
|
||||
Reference in New Issue
Block a user