Files
TechHelper/TechHelper.Server/Services/Submission/SubmissionService.cs
SpecialX ac900159ba
Some checks failed
TechAct / explore-gitea-actions (push) Failing after 12s
重构项目结构,移除Assignment相关功能,优化Submission模块
2025-10-09 18:57:28 +08:00

506 lines
15 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using AutoMapper;
using Entities.Contracts;
using Entities.DTO;
using Microsoft.EntityFrameworkCore;
using SharedDATA.Api;
using SharedDATA.Context;
using TechHelper.Services.Beta;
namespace TechHelper.Services.Beta
{
/// <summary>
/// 提交服务实现Beta版本
/// 实现提交相关的业务逻辑操作
/// </summary>
public class SubmissionService : ISubmissionService
{
private readonly IUnitOfWork _unitOfWork;
private readonly IMapper _mapper;
private readonly IRepository<Submission> _submissionRepository;
private readonly IRepository<SubmissionDetail> _submissionDetailRepository;
/// <summary>
/// 初始化提交服务
/// </summary>
/// <param name="mapper">AutoMapper实例</param>
/// <param name="unitOfWork">工作单元</param>
public SubmissionService(IMapper mapper, IUnitOfWork unitOfWork)
{
_mapper = mapper;
_unitOfWork = unitOfWork;
_submissionRepository = _unitOfWork.GetRepository<Submission>();
_submissionDetailRepository = _unitOfWork.GetRepository<SubmissionDetail>();
}
#region CRUD操作
/// <summary>
/// 获取所有提交记录
/// </summary>
/// <param name="query">查询参数</param>
/// <returns>提交记录列表</returns>
public async Task<ApiResponse> GetAllAsync(QueryParameter query)
{
try
{
var pagedSubmissions = await _submissionRepository.GetPagedListAsync(
pageIndex: query.PageIndex,
pageSize: query.PageSize,
orderBy: s => s.OrderByDescending(s => s.SubmissionTime),
predicate: s => !s.IsDeleted);
var submissionDtos = _mapper.Map<List<SubmissionListDto>>(pagedSubmissions.Items);
return ApiResponse.Success("获取所有提交成功。", submissionDtos);
}
catch (Exception ex)
{
return ApiResponse.Error($"获取所有提交失败: {ex.Message}");
}
}
/// <summary>
/// 根据ID获取提交记录
/// </summary>
/// <param name="id">提交ID</param>
/// <returns>提交记录详情</returns>
public async Task<ApiResponse> GetAsync(Guid id)
{
try
{
var submission = await _submissionRepository.GetFirstOrDefaultAsync(
predicate: s => s.Id == id && !s.IsDeleted);
if (submission == null)
{
return ApiResponse.Error("未找到提交记录。", 404);
}
var submissionDto = _mapper.Map<SubmissionDto>(submission);
return ApiResponse.Success("获取提交记录成功。", submissionDto);
}
catch (Exception ex)
{
return ApiResponse.Error($"获取提交记录失败: {ex.Message}");
}
}
/// <summary>
/// 创建提交记录
/// </summary>
/// <param name="model">提交数据传输对象</param>
/// <returns>创建结果</returns>
public async Task<ApiResponse> AddAsync(SubmissionDto model)
{
try
{
var submission = _mapper.Map<Submission>(model);
submission.SubmissionTime = DateTime.Now;
submission.IsDeleted = false;
await _submissionRepository.InsertAsync(submission);
await _unitOfWork.SaveChangesAsync();
var result = _mapper.Map<SubmissionDto>(submission);
return ApiResponse.Success("提交成功。", result);
}
catch (Exception ex)
{
return ApiResponse.Error($"创建提交失败: {ex.Message}");
}
}
/// <summary>
/// 更新提交记录
/// </summary>
/// <param name="model">提交数据传输对象</param>
/// <returns>更新结果</returns>
public async Task<ApiResponse> UpdateAsync(SubmissionDto model)
{
try
{
var existingSubmission = await _submissionRepository.GetFirstOrDefaultAsync(predicate: s => s.Id == model.Id && !s.IsDeleted);
if (existingSubmission == null)
{
return ApiResponse.Error("未找到要更新的提交记录。", 404);
}
_mapper.Map(model, existingSubmission);
_submissionRepository.Update(existingSubmission);
await _unitOfWork.SaveChangesAsync();
var result = _mapper.Map<SubmissionDto>(existingSubmission);
return ApiResponse.Success("更新提交记录成功。", result);
}
catch (Exception ex)
{
return ApiResponse.Error($"更新提交记录失败: {ex.Message}");
}
}
/// <summary>
/// 删除提交记录
/// </summary>
/// <param name="id">提交ID</param>
/// <returns>删除结果</returns>
public async Task<ApiResponse> DeleteAsync(Guid id)
{
try
{
var submission = await _submissionRepository.GetFirstOrDefaultAsync(predicate: s => s.Id == id && !s.IsDeleted);
if (submission == null)
{
return ApiResponse.Error("未找到要删除的提交记录。", 404);
}
submission.IsDeleted = true;
_submissionRepository.Update(submission);
var submissionDetails = await _submissionDetailRepository.GetPagedListAsync(predicate: sd => sd.SubmissionId == id);
foreach (var detail in submissionDetails.Items)
{
detail.IsDeleted = true;
_submissionDetailRepository.Update(detail);
}
await _unitOfWork.SaveChangesAsync();
return ApiResponse.Success("提交记录及相关详情删除成功。", null);
}
catch (Exception ex)
{
return ApiResponse.Error($"删除提交记录失败: {ex.Message}");
}
}
#endregion
#region
/// <summary>
/// 获取用户的错题列表
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns>错题列表</returns>
public async Task<ApiResponse> GetAllErrorQuestionsAsync(Guid userId)
{
try
{
var errorSDs = await _submissionDetailRepository.GetPagedListAsync(
predicate: sd => sd.StudentId == userId && sd.IsCorrect == false,
include: i => i
.Include(s => s.ExamQuestion)
.ThenInclude(aq => aq.Question));
var errorQuestions = errorSDs.Items.Select(sd => sd.ExamQuestion.Question)
.Where(q => q != null)
.DistinctBy(q => q.Id)
.ToList();
var result = _mapper.Map<List<QuestionDto>>(errorQuestions);
return ApiResponse.Success("获取所有错题成功。", result);
}
catch (Exception ex)
{
return ApiResponse.Error($"获取所有错题失败: {ex.Message}");
}
}
/// <summary>
/// 获取指定作业的错题列表
/// </summary>
/// <param name="assignmentId">作业ID</param>
/// <param name="userId">用户ID</param>
/// <returns>错题列表</returns>
public async Task<ApiResponse> GetAssignmentErrorQuestionsAsync(Guid assignmentId, Guid userId)
{
try
{
var errorSDs = await _submissionDetailRepository.GetPagedListAsync(
predicate: sd => sd.Submission.ExamId == assignmentId &&
sd.StudentId == userId &&
sd.IsCorrect == false,
include: i => i
.Include(s => s.ExamQuestion)
.ThenInclude(aq => aq.Question));
var errorQuestions = errorSDs.Items.Select(sd => sd.ExamQuestion.Question)
.Where(q => q != null)
.DistinctBy(q => q.Id)
.ToList();
var result = _mapper.Map<List<QuestionDto>>(errorQuestions);
return ApiResponse.Success("获取指定作业错题成功。", result);
}
catch (Exception ex)
{
return ApiResponse.Error($"获取指定作业错题失败: {ex.Message}");
}
}
/// <summary>
/// 获取错题类型分布
/// </summary>
/// <param name="assignmentId">作业ID</param>
/// <param name="userId">用户ID</param>
/// <returns>错题类型分布</returns>
public async Task<ApiResponse> GetAssignmentErrorQuestionTypeDisAsync(Guid assignmentId, Guid userId)
{
try
{
var errorSDs = await _submissionDetailRepository.GetPagedListAsync(
predicate: sd => sd.Submission.ExamId == assignmentId &&
sd.StudentId == userId &&
sd.IsCorrect == false,
include: i => i
.Include(s => s.ExamQuestion)
.ThenInclude(aq => aq.Question));
var errorTypeDistribution = errorSDs.Items
.Where(sd => sd.ExamQuestion?.Question?.QuestionType != null)
.GroupBy(sd => sd.ExamQuestion.Question.QuestionType.Name)
.Select(g => new
{
QuestionType = g.Key.ToString(),
Count = g.Count()
})
.ToList();
return ApiResponse.Success("获取指定作业错题类型分布成功。", errorTypeDistribution);
}
catch (Exception ex)
{
return ApiResponse.Error($"获取指定作业错题类型分布失败: {ex.Message}");
}
}
/// <summary>
/// 获取所有错题类型分布
/// </summary>
/// <param name="assignmentId">作业ID</param>
/// <param name="userId">用户ID</param>
/// <returns>错题类型分布</returns>
public async Task<ApiResponse> GetAllErrorQuestionTypeDisAsync(Guid assignmentId, Guid userId)
{
try
{
var errorSDs = await _submissionDetailRepository.GetPagedListAsync(
predicate: sd => sd.Submission.ExamId == assignmentId &&
sd.StudentId == userId &&
sd.IsCorrect == false,
include: i => i
.Include(s => s.ExamQuestion)
.ThenInclude(aq => aq.Question));
var errorTypeDistribution = errorSDs.Items
.Where(sd => sd.ExamQuestion?.Question?.QuestionType != null)
.GroupBy(sd => sd.ExamQuestion.Question.QuestionType.Name)
.Select(g => new
{
QuestionType = g.Key.ToString(),
Count = g.Count()
})
.ToList();
return ApiResponse.Success("获取错题类型分布成功。", errorTypeDistribution);
}
catch (Exception ex)
{
return ApiResponse.Error($"获取错题类型分布失败: {ex.Message}");
}
}
/// <summary>
/// 获取作业中所有学生的错题情况
/// </summary>
/// <param name="assignmentId">作业ID</param>
/// <param name="teacherId">教师ID</param>
/// <returns>学生错题情况</returns>
public async Task<ApiResponse> GetAssignmentAllStudentsError(Guid assignmentId, Guid teacherId)
{
try
{
var submissionDetails = await _submissionDetailRepository.GetPagedListAsync(
predicate: sd => sd.Submission.ExamId == assignmentId &&
sd.IsCorrect == false,
include: i => i.Include(sd => sd.Student));
var studentsErrorSummary = submissionDetails.Items
.Where(sd => sd.Student != null)
.GroupBy(sd => new { sd.StudentId, sd.Student.UserName })
.Select(g => new
{
StudentId = g.Key.StudentId,
StudentName = g.Key.UserName,
ErrorQuestionCount = g.Count()
})
.ToList();
return ApiResponse.Success("获取作业中所有学生的错题情况成功。", studentsErrorSummary);
}
catch (Exception ex)
{
return ApiResponse.Error($"获取作业中所有学生的错题情况失败: {ex.Message}");
}
}
/// <summary>
/// 获取出现错题的学生列表
/// </summary>
/// <param name="assignmentQuestionId">作业题目ID</param>
/// <returns>错题学生列表</returns>
public async Task<ApiResponse> GetQuestionErrorStudents(Guid assignmentQuestionId)
{
try
{
var errorSubmissionDetails = await _submissionDetailRepository.GetPagedListAsync(
predicate: sd => sd.ExamQuestionId == assignmentQuestionId &&
sd.IsCorrect == false,
include: i => i
.Include(sd => sd.Student)
.Include(sd => sd.ExamQuestion)
.ThenInclude(aq => aq.Question));
var errorStudentsByQuestion = errorSubmissionDetails.Items
.Where(sd => sd.ExamQuestion?.Question != null && sd.Student != null)
.GroupBy(sd => new { sd.ExamQuestionId, sd.ExamQuestion.Question.Title })
.Select(g => new
{
AssignmentQuestionId = g.Key.ExamQuestionId,
QuestionTitle = g.Key.Title,
ErrorStudents = g.Select(sd => new
{
StudentId = sd.StudentId,
StudentName = sd.Student.UserName
}).Distinct().ToList()
})
.ToList();
return ApiResponse.Success("获取出现错题的学生成功。", errorStudentsByQuestion);
}
catch (Exception ex)
{
return ApiResponse.Error($"获取出现错题的学生失败: {ex.Message}");
}
}
#endregion
#region
/// <summary>
/// 判断是否已经存在提交记录
/// </summary>
/// <param name="assignmentId">作业ID</param>
/// <param name="studentId">学生ID</param>
/// <returns>提交记录数量</returns>
public async Task<byte> IsHasSubmissionAsync(Guid assignmentId, Guid studentId)
{
try
{
var result = await _unitOfWork.GetRepository<Submission>().GetAllAsync(predicate: s => s.ExamId == assignmentId && s.StudentId == studentId);
return (byte)result.Count;
}
catch (Exception ex)
{
throw;
}
}
/// <summary>
/// 获取学生提交摘要
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns>学生提交摘要列表</returns>
public async Task<ApiResponse> GetStudentSubmissionSummariesAsync(Guid userId)
{
try
{
var submissions = await _submissionRepository.GetPagedListAsync(
predicate: s => s.StudentId == userId && !s.IsDeleted,
orderBy: s => s.OrderByDescending(s => s.SubmissionTime));
var summaries = submissions.Items.Select(s => new StudentSubmissionSummaryDto
{
Id = s.Id,
AssignmentName = s.Exam?.Title ?? "未知作业",
CreatedDate = s.SubmissionTime,
Score = s.OverallGrade,
StudentName = s.Student?.UserName ?? "未知学生",
Status = s.Status.GetDisplayName()
}).ToList();
return ApiResponse.Success("获取学生提交摘要成功。", new StudentSubmissionSummaryResponseDto
{
Submissions = summaries,
TotalCount = submissions.TotalCount
});
}
catch (Exception ex)
{
return ApiResponse.Error($"获取学生提交摘要失败: {ex.Message}");
}
}
/// <summary>
/// 获取学生提交详情
/// </summary>
/// <param name="submissionId">提交ID</param>
/// <returns>学生提交详情</returns>
public async Task<ApiResponse> GetStudentSubmissionDetailAsync(Guid submissionId)
{
try
{
var submission = await _submissionRepository.GetFirstOrDefaultAsync(
predicate: s => s.Id == submissionId && !s.IsDeleted);
if (submission == null)
{
return ApiResponse.Error("未找到提交记录。", 404);
}
var detail = _mapper.Map<StudentSubmissionDetailDto>(submission);
return ApiResponse.Success("获取学生提交详情成功。", detail);
}
catch (Exception ex)
{
return ApiResponse.Error($"获取学生提交详情失败: {ex.Message}");
}
}
public async Task<ApiResponse> GradeExam(SubmissionTeacherUpdateDto model)
{
try
{
var existingSubmission = await _submissionRepository.GetFirstOrDefaultAsync(predicate: s => s.Id == model.Id && !s.IsDeleted);
if (existingSubmission == null)
{
return ApiResponse.Error("未找到要批改的试卷记录。", 404);
}
_mapper.Map(model, existingSubmission);
foreach (var item in existingSubmission.SubmissionDetails)
{
var sdd = model.SubmissionUpdateDetails.FirstOrDefault(d => d.Id == item.Id);
if (sdd == null) continue;
_mapper.Map(sdd, item);
}
_submissionRepository.Update(existingSubmission);
await _unitOfWork.SaveChangesAsync();
var result = _mapper.Map<SubmissionDto>(existingSubmission);
return ApiResponse.Success("批改试卷记录成功。", result);
}
catch (Exception ex)
{
return ApiResponse.Error($"批改试卷记录失败: {ex.Message}");
}
}
#endregion
}
}