1
This commit is contained in:
@@ -76,4 +76,15 @@ namespace Entities.Contracts
|
|||||||
Option
|
Option
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public enum SubmissionStatus
|
||||||
|
{
|
||||||
|
Pending, // 待提交/未开始
|
||||||
|
Submitted, // 已提交
|
||||||
|
Graded, // 已批改
|
||||||
|
Resubmission, // 待重新提交 (如果允许)
|
||||||
|
Late, // 迟交
|
||||||
|
Draft, // 草稿
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -31,6 +31,9 @@ namespace Entities.Contracts
|
|||||||
[Column("question_number")]
|
[Column("question_number")]
|
||||||
public byte Index { get; set; }
|
public byte Index { get; set; }
|
||||||
|
|
||||||
|
[Column("sequence")]
|
||||||
|
public string Sequence { get; set; } = string.Empty;
|
||||||
|
|
||||||
[Column("parent_question_group_id")]
|
[Column("parent_question_group_id")]
|
||||||
public Guid? ParentAssignmentQuestionId { get; set; }
|
public Guid? ParentAssignmentQuestionId { get; set; }
|
||||||
|
|
||||||
|
@@ -37,7 +37,7 @@ namespace Entities.Contracts
|
|||||||
public float? OverallGrade { get; set; }
|
public float? OverallGrade { get; set; }
|
||||||
|
|
||||||
[Column("overall_feedback")]
|
[Column("overall_feedback")]
|
||||||
public string OverallFeedback { get; set; }
|
public string? OverallFeedback { get; set; }
|
||||||
|
|
||||||
[Column("graded_by")]
|
[Column("graded_by")]
|
||||||
[ForeignKey("Grader")]
|
[ForeignKey("Grader")]
|
||||||
@@ -66,13 +66,4 @@ namespace Entities.Contracts
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SubmissionStatus
|
|
||||||
{
|
|
||||||
Pending, // 待提交/未开始
|
|
||||||
Submitted, // 已提交
|
|
||||||
Graded, // 已批改
|
|
||||||
Resubmission, // 待重新提交 (如果允许)
|
|
||||||
Late, // 迟交
|
|
||||||
Draft, // 草稿
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -31,16 +31,16 @@ namespace Entities.Contracts
|
|||||||
public Guid AssignmentQuestionId { get; set; }
|
public Guid AssignmentQuestionId { get; set; }
|
||||||
|
|
||||||
[Column("student_answer")]
|
[Column("student_answer")]
|
||||||
public string StudentAnswer { get; set; }
|
public string? StudentAnswer { get; set; }
|
||||||
|
|
||||||
[Column("is_correct")]
|
[Column("is_correct")]
|
||||||
public bool? IsCorrect { get; set; }
|
public bool? IsCorrect { get; set; }
|
||||||
|
|
||||||
[Column("points_awarded")]
|
[Column("points_awarded")]
|
||||||
public float? PointsAwarded { get; set; }
|
public float? PointsAwarded { get; set; } // score
|
||||||
|
|
||||||
[Column("teacher_feedback")]
|
[Column("teacher_feedback")]
|
||||||
public string TeacherFeedback { get; set; }
|
public string? TeacherFeedback { get; set; }
|
||||||
|
|
||||||
[Column("created_at")]
|
[Column("created_at")]
|
||||||
public DateTime CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
@@ -54,8 +54,10 @@ namespace Entities.Contracts
|
|||||||
[ForeignKey(nameof(StudentId))]
|
[ForeignKey(nameof(StudentId))]
|
||||||
public User Student { get; set; }
|
public User Student { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey(nameof(SubmissionId))]
|
||||||
public Submission Submission { get; set; }
|
public Submission Submission { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey(nameof(AssignmentQuestionId))]
|
||||||
public AssignmentQuestion AssignmentQuestion { get; set; }
|
public AssignmentQuestion AssignmentQuestion { get; set; }
|
||||||
|
|
||||||
public SubmissionDetail()
|
public SubmissionDetail()
|
||||||
|
23
Entities/DTO/AssignmentClassDto.cs
Normal file
23
Entities/DTO/AssignmentClassDto.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using Entities.Contracts;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace Entities.DTO
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
public class AssignmentClassDto
|
||||||
|
{
|
||||||
|
public AssignmentDto Assignment { get; set; }
|
||||||
|
public Class ClassId { get; set; }
|
||||||
|
public DateTime AssignedAt { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using Entities.Contracts;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -6,4 +7,20 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Entities.DTO
|
namespace Entities.DTO
|
||||||
{
|
{
|
||||||
|
public class AssignmentDto
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; } = Guid.Empty;
|
||||||
|
public string Title { get; set; } = string.Empty;
|
||||||
|
public string Description { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public byte TotalQuestions { get; set; }
|
||||||
|
public float Score { get; set; } = 0;
|
||||||
|
public SubjectAreaEnum SubjectArea { get; set; } = SubjectAreaEnum.Unknown;
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public DateTime UpdatedAt { get; set; }
|
||||||
|
public DateTime DueDate { get; set; }
|
||||||
|
public Guid CreatorId { get; set; }
|
||||||
|
|
||||||
|
public AssignmentQuestionDto ExamStruct { get; set; } = new AssignmentQuestionDto();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,7 @@ namespace Entities.DTO
|
|||||||
|
|
||||||
public byte Index { get; set; } = 0;
|
public byte Index { get; set; } = 0;
|
||||||
public float Score { get; set; } = 0;
|
public float Score { get; set; } = 0;
|
||||||
|
public string Sequence { get; set; } = string.Empty;
|
||||||
|
|
||||||
public Layout Layout { get; set; } = Layout.horizontal;
|
public Layout Layout { get; set; } = Layout.horizontal;
|
||||||
public AssignmentStructType StructType { get; set; } = AssignmentStructType.Question;
|
public AssignmentStructType StructType { get; set; } = AssignmentStructType.Question;
|
||||||
@@ -24,4 +25,6 @@ namespace Entities.DTO
|
|||||||
|
|
||||||
public QuestionDto? Question { get; set; }
|
public QuestionDto? Question { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,46 +0,0 @@
|
|||||||
using Entities.Contracts;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace Entities.DTO
|
|
||||||
{
|
|
||||||
public class AssignmentDto
|
|
||||||
{
|
|
||||||
public Guid Id { get; set; } = Guid.Empty;
|
|
||||||
public string Title { get; set; } = string.Empty;
|
|
||||||
public string Description { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public byte TotalQuestions { get; set; }
|
|
||||||
public float Score { get; set; } = 0;
|
|
||||||
public SubjectAreaEnum SubjectArea { get; set; } = SubjectAreaEnum.Unknown;
|
|
||||||
public DateTime CreatedAt { get; set; }
|
|
||||||
public DateTime UpdatedAt { get; set; }
|
|
||||||
public DateTime DueDate { get; set; }
|
|
||||||
public Guid CreatorId { get; set; }
|
|
||||||
|
|
||||||
public AssignmentQuestionDto ExamStruct { get; set; } = new AssignmentQuestionDto();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AssignmentClassDto
|
|
||||||
{
|
|
||||||
public AssignmentDto Assignment { get; set; }
|
|
||||||
public Class ClassId { get; set; }
|
|
||||||
public DateTime AssignedAt { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class QuestionContextDto
|
|
||||||
{
|
|
||||||
public Guid Id { get; set; } = Guid.Empty;
|
|
||||||
public string Description { get; set; } = string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class OptionDto
|
|
||||||
{
|
|
||||||
public string? Value { get; set; } = string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
15
Entities/DTO/QuestionContextDto.cs
Normal file
15
Entities/DTO/QuestionContextDto.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Entities.DTO
|
||||||
|
{
|
||||||
|
|
||||||
|
public class QuestionContextDto
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; } = Guid.Empty;
|
||||||
|
public string Description { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
@@ -36,4 +36,13 @@ namespace Entities.DTO
|
|||||||
public DateTime UpdatedAt { get; set; } = DateTime.Now;
|
public DateTime UpdatedAt { get; set; } = DateTime.Now;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Can be removed because the class isn't used
|
||||||
|
/// </summary>
|
||||||
|
public class OptionDto
|
||||||
|
{
|
||||||
|
public string? Value { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
20
Entities/DTO/StudentDto.cs
Normal file
20
Entities/DTO/StudentDto.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using Entities.Contracts;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Entities.DTO
|
||||||
|
{
|
||||||
|
public class StudentDto
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string? DisplayName { get; set; }
|
||||||
|
|
||||||
|
public UInt32 ErrorQuestionNum { get; set; }
|
||||||
|
public Dictionary<QuestionType, UInt32> ErrorQuestionTypes { get; set; } = new Dictionary<QuestionType, UInt32>();
|
||||||
|
public Dictionary<SubjectAreaEnum, UInt32> SubjectAreaErrorQuestionDis { get; set; } = new Dictionary<SubjectAreaEnum, UInt32>();
|
||||||
|
public Dictionary<byte, UInt32> LessonErrorDis { get; set; } = new Dictionary<byte, UInt32>();
|
||||||
|
}
|
||||||
|
}
|
19
Entities/DTO/SubmissionDetailDto.cs
Normal file
19
Entities/DTO/SubmissionDetailDto.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Entities.DTO
|
||||||
|
{
|
||||||
|
public class SubmissionDetailDto
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; } = Guid.Empty;
|
||||||
|
public Guid StudentId { get; set; }
|
||||||
|
public Guid AssignmentQuestionId { get; set; }
|
||||||
|
public string? StudentAnswer { get; set; }
|
||||||
|
public bool? IsCorrect { get; set; }
|
||||||
|
public float? PointsAwarded { get; set; }
|
||||||
|
public string? TeacherFeedback { get; set; }
|
||||||
|
}
|
||||||
|
}
|
23
Entities/DTO/SubmissionDto.cs
Normal file
23
Entities/DTO/SubmissionDto.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using Entities.Contracts;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Entities.DTO
|
||||||
|
{
|
||||||
|
public class SubmissionDto
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; } = Guid.Empty;
|
||||||
|
public Guid AssignmentId { get; set; }
|
||||||
|
public Guid StudentId { get; set; }
|
||||||
|
public DateTime SubmissionTime { get; set; }
|
||||||
|
public float OverallGrade { get; set; } = 0;
|
||||||
|
public string OverallFeedback { get; set; } = string.Empty;
|
||||||
|
public Guid? GraderId { get; set; }
|
||||||
|
public DateTime? GradedAt { get; set; }
|
||||||
|
public SubmissionStatus Status { get; set; }
|
||||||
|
public List<SubmissionDetailDto> SubmissionDetails { get; set; } = new List<SubmissionDetailDto>();
|
||||||
|
}
|
||||||
|
}
|
15
Entities/DTO/UserDto.cs
Normal file
15
Entities/DTO/UserDto.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Entities.DTO
|
||||||
|
{
|
||||||
|
public class UserDto
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string? DisplayName { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -15,6 +15,9 @@ namespace TechHelper.Context
|
|||||||
CreateMap<AssignmentQuestionEx, AssignmentQuestionDto>()
|
CreateMap<AssignmentQuestionEx, AssignmentQuestionDto>()
|
||||||
.ForMember(d=>d.Description, o=>o.Ignore());
|
.ForMember(d=>d.Description, o=>o.Ignore());
|
||||||
CreateMap<AssignmentEx, AssignmentDto>();
|
CreateMap<AssignmentEx, AssignmentDto>();
|
||||||
|
|
||||||
|
|
||||||
|
CreateMap<AssignmentCheckData, Submission>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,18 +2,20 @@
|
|||||||
|
|
||||||
namespace TechHelper.Client.Exam
|
namespace TechHelper.Client.Exam
|
||||||
{
|
{
|
||||||
public class ExamStruct
|
public class AssignmentCheckData
|
||||||
{
|
{
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public List<QuestionItem> Questions { get; set; } = new List<QuestionItem>();
|
public Guid AssignmentId { get; set; }
|
||||||
|
public Guid StudentId { get; set; }
|
||||||
|
public List<AssignmentCheckQuestion> Questions { get; set; } = new List<AssignmentCheckQuestion>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public class QuestionItem
|
public class AssignmentCheckQuestion
|
||||||
{
|
{
|
||||||
public string Sequence { get; set; } = string.Empty;
|
public string Sequence { get; set; } = string.Empty;
|
||||||
public string QuestionText { get; set; } = string.Empty;
|
public AssignmentQuestionDto AssignmentQuestionDto { get; set; } = new AssignmentQuestionDto();
|
||||||
public float Score { get; set; }
|
public float Score { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Student
|
public class Student
|
||||||
@@ -24,32 +26,32 @@ namespace TechHelper.Client.Exam
|
|||||||
|
|
||||||
public class QuestionAnswerStatus
|
public class QuestionAnswerStatus
|
||||||
{
|
{
|
||||||
public string QuestionSequence { get; set; } = string.Empty; // 题目序号,例如 "1.1"
|
public string QuestionSequence { get; set; } = string.Empty; // 题目序号,例如 "1.1"
|
||||||
public string QuestionText { get; set; } = string.Empty; // 题目文本
|
public string QuestionText { get; set; } = string.Empty; // 题目文本
|
||||||
public float QuestionScore { get; set; } // 题目分值
|
public float QuestionScore { get; set; } // 题目分值
|
||||||
public Dictionary<Guid, bool> StudentCorrectStatus { get; set; } = new Dictionary<Guid, bool>();
|
public Dictionary<Guid, bool> StudentCorrectStatus { get; set; } = new Dictionary<Guid, bool>();
|
||||||
// Key: Student.Id, Value: true 表示正确,false 表示错误
|
// Key: Student.Id, Value: true 表示正确,false 表示错误
|
||||||
}
|
}
|
||||||
|
|
||||||
public class QuestionRowData
|
public class QuestionRowData
|
||||||
{
|
{
|
||||||
public ExamStruct.QuestionItem QuestionItem { get; set; } // 原始题目信息
|
public AssignmentCheckQuestion QuestionItem { get; set; } // 原始题目信息
|
||||||
public Dictionary<Guid, bool> StudentAnswers { get; set; } = new Dictionary<Guid, bool>();
|
public Dictionary<Guid, bool> StudentAnswers { get; set; } = new Dictionary<Guid, bool>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class ExamStructExtensions
|
public static class ExamStructExtensions
|
||||||
{
|
{
|
||||||
public static ExamStruct GetStruct(this AssignmentDto dto)
|
public static AssignmentCheckData GetStruct(this AssignmentDto dto)
|
||||||
{
|
{
|
||||||
if (dto == null)
|
if (dto == null)
|
||||||
{
|
{
|
||||||
return new ExamStruct { Title = "无效试卷", Questions = new List<ExamStruct.QuestionItem>() };
|
return new AssignmentCheckData { Title = "无效试卷", Questions = new List<AssignmentCheckQuestion>() };
|
||||||
}
|
}
|
||||||
|
|
||||||
var examStruct = new ExamStruct
|
var examStruct = new AssignmentCheckData
|
||||||
{
|
{
|
||||||
Title = dto.Title
|
Title = dto.Title
|
||||||
};
|
};
|
||||||
|
|
||||||
GetSeqRecursive(dto.ExamStruct, null, examStruct.Questions);
|
GetSeqRecursive(dto.ExamStruct, null, examStruct.Questions);
|
||||||
@@ -65,8 +67,8 @@ namespace TechHelper.Client.Exam
|
|||||||
/// <param name="allQuestions">用于收集所有生成题目项的列表。</param>
|
/// <param name="allQuestions">用于收集所有生成题目项的列表。</param>
|
||||||
private static void GetSeqRecursive(
|
private static void GetSeqRecursive(
|
||||||
AssignmentQuestionDto currentGroup,
|
AssignmentQuestionDto currentGroup,
|
||||||
string? parentSequence,
|
string? parentSequence,
|
||||||
List<ExamStruct.QuestionItem> allQuestions)
|
List<AssignmentCheckQuestion> allQuestions)
|
||||||
{
|
{
|
||||||
string currentGroupSequence = parentSequence != null
|
string currentGroupSequence = parentSequence != null
|
||||||
? $"{parentSequence}.{currentGroup.Index}"
|
? $"{parentSequence}.{currentGroup.Index}"
|
||||||
@@ -76,6 +78,17 @@ namespace TechHelper.Client.Exam
|
|||||||
{
|
{
|
||||||
GetSeqRecursive(subGroup, currentGroupSequence, allQuestions);
|
GetSeqRecursive(subGroup, currentGroupSequence, allQuestions);
|
||||||
}
|
}
|
||||||
|
if (!string.IsNullOrEmpty(currentGroup.Sequence))
|
||||||
|
{
|
||||||
|
|
||||||
|
allQuestions.Add(new AssignmentCheckQuestion
|
||||||
|
{
|
||||||
|
AssignmentQuestionDto = currentGroup,
|
||||||
|
//Sequence = currentGroupSequence,
|
||||||
|
Sequence = currentGroup.Sequence,
|
||||||
|
Score = currentGroup.Score,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -7,7 +7,7 @@ using AutoMapper;
|
|||||||
|
|
||||||
namespace TechHelper.Client.Exam
|
namespace TechHelper.Client.Exam
|
||||||
{
|
{
|
||||||
public static class ExamPaperExtensions
|
public static class AssignmentExtensions
|
||||||
{
|
{
|
||||||
|
|
||||||
public static List<string> ParseOptionsFromText(this string optionsText)
|
public static List<string> ParseOptionsFromText(this string optionsText)
|
||||||
@@ -25,9 +25,9 @@ namespace TechHelper.Client.Exam
|
|||||||
public static void SeqQGroupIndex(this AssignmentQuestionDto dto)
|
public static void SeqQGroupIndex(this AssignmentQuestionDto dto)
|
||||||
{
|
{
|
||||||
|
|
||||||
foreach(var sqg in dto.ChildrenAssignmentQuestion)
|
foreach (var sqg in dto.ChildrenAssignmentQuestion)
|
||||||
{
|
{
|
||||||
sqg.Index = (byte)dto.ChildrenAssignmentQuestion.IndexOf(sqg);
|
sqg.Index = (byte)(dto.ChildrenAssignmentQuestion.IndexOf(sqg) + 1);
|
||||||
sqg.SeqQGroupIndex();
|
sqg.SeqQGroupIndex();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -56,6 +56,7 @@ namespace TechHelper.Client.Exam
|
|||||||
public string Description { get; set; } = string.Empty;
|
public string Description { get; set; } = string.Empty;
|
||||||
public byte Index { get; set; } = 0;
|
public byte Index { get; set; } = 0;
|
||||||
public float Score { get; set; }
|
public float Score { get; set; }
|
||||||
|
public string Sequence { get; set; } = string.Empty;
|
||||||
public QuestionEx? Question { get; set; }
|
public QuestionEx? Question { get; set; }
|
||||||
public AssignmentStructType Type { get; set; }
|
public AssignmentStructType Type { get; set; }
|
||||||
public List<AssignmentQuestionEx> ChildrenAssignmentQuestion { get; set; } = new List<AssignmentQuestionEx>();
|
public List<AssignmentQuestionEx> ChildrenAssignmentQuestion { get; set; } = new List<AssignmentQuestionEx>();
|
||||||
@@ -344,6 +345,8 @@ namespace TechHelper.Client.Exam
|
|||||||
assignmentQuestionStack.Pop();
|
assignmentQuestionStack.Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string sequence = assignmentQuestionStack.Count > 0 ? assignmentQuestionStack.Peek().Sequence : string.Empty;
|
||||||
|
|
||||||
// 验证捕获组:Group 1 是编号,Group 2 是题目内容
|
// 验证捕获组:Group 1 是编号,Group 2 是题目内容
|
||||||
if (pm.RegexMatch.Groups.Count < 3 || !pm.RegexMatch.Groups[1].Success || string.IsNullOrWhiteSpace(pm.RegexMatch.Groups[2].Value))
|
if (pm.RegexMatch.Groups.Count < 3 || !pm.RegexMatch.Groups[1].Success || string.IsNullOrWhiteSpace(pm.RegexMatch.Groups[2].Value))
|
||||||
{
|
{
|
||||||
@@ -372,6 +375,8 @@ namespace TechHelper.Client.Exam
|
|||||||
// 提取标题,这里使用 Group 2 的值,它不包含分数
|
// 提取标题,这里使用 Group 2 的值,它不包含分数
|
||||||
string title = pm.RegexMatch.Groups[2].Value.Trim();
|
string title = pm.RegexMatch.Groups[2].Value.Trim();
|
||||||
|
|
||||||
|
string seq = pm.RegexMatch.Groups[1].Value.Trim();
|
||||||
|
seq = string.IsNullOrEmpty(seq) || string.IsNullOrEmpty(sequence) ? seq : " ." + seq;
|
||||||
|
|
||||||
AssignmentQuestionEx newAssignmentQuestion;
|
AssignmentQuestionEx newAssignmentQuestion;
|
||||||
if (pm.PatternConfig.Type == AssignmentStructType.Struct)
|
if (pm.PatternConfig.Type == AssignmentStructType.Struct)
|
||||||
@@ -380,6 +385,7 @@ namespace TechHelper.Client.Exam
|
|||||||
{
|
{
|
||||||
Title = title,
|
Title = title,
|
||||||
Score = score,
|
Score = score,
|
||||||
|
Sequence = sequence + seq,
|
||||||
Priority = pm.PatternConfig.Priority,
|
Priority = pm.PatternConfig.Priority,
|
||||||
Type = pm.PatternConfig.Type
|
Type = pm.PatternConfig.Type
|
||||||
};
|
};
|
||||||
@@ -390,6 +396,7 @@ namespace TechHelper.Client.Exam
|
|||||||
{
|
{
|
||||||
Priority = pm.PatternConfig.Priority,
|
Priority = pm.PatternConfig.Priority,
|
||||||
Type = pm.PatternConfig.Type,
|
Type = pm.PatternConfig.Type,
|
||||||
|
Sequence = sequence + seq,
|
||||||
Score = score,
|
Score = score,
|
||||||
Question = new QuestionEx
|
Question = new QuestionEx
|
||||||
{
|
{
|
||||||
|
@@ -92,7 +92,6 @@ namespace TechHelper.Client.HttpRepository
|
|||||||
|
|
||||||
public async Task<ResponseDto> RegisterUserAsync(UserForRegistrationDto userForRegistrationDto)
|
public async Task<ResponseDto> RegisterUserAsync(UserForRegistrationDto userForRegistrationDto)
|
||||||
{
|
{
|
||||||
// 移除 using (_client = _clientFactory.CreateClient("Default"))
|
|
||||||
userForRegistrationDto.ClientURI = Path.Combine(
|
userForRegistrationDto.ClientURI = Path.Combine(
|
||||||
_navigationManager.BaseUri, "emailconfirmation");
|
_navigationManager.BaseUri, "emailconfirmation");
|
||||||
|
|
||||||
|
@@ -9,216 +9,227 @@
|
|||||||
|
|
||||||
@if (_isLoading)
|
@if (_isLoading)
|
||||||
{
|
{
|
||||||
<MudProgressCircular Indeterminate="true" Color="Color.Primary" Class="d-flex justify-center my-8" />
|
<MudProgressCircular Indeterminate="true" Color="Color.Primary" Class="d-flex justify-center my-8" />
|
||||||
<MudText Class="text-center">正在加载试卷和学生数据...</MudText>
|
<MudText Class="text-center">正在加载试卷和学生数据...</MudText>
|
||||||
}
|
}
|
||||||
else if (_questionsForTable.Any() && _students.Any())
|
else if (_questionsForTable.Any() && _students.Any())
|
||||||
{
|
{
|
||||||
<MudTable @ref="_table" T="QuestionRowData" Items="@_questionsForTable" Hover="true" Breakpoint="Breakpoint.Sm" Class="mud-elevation-2" Dense="true">
|
<MudTable @ref="_table" T="QuestionRowData" Items="@_questionsForTable" Hover="true" Breakpoint="Breakpoint.Sm" Striped="true" Class="mud-elevation-2" Dense="true">
|
||||||
<HeaderContent>
|
<HeaderContent>
|
||||||
<MudTh Style="width:100px;">序号</MudTh>
|
<MudTh Style="width:100px;">序号</MudTh>
|
||||||
<MudTh Style="width:80px; text-align:center;">分值</MudTh>
|
<MudTh Style="width:80px; text-align:center;">分值</MudTh>
|
||||||
@foreach (var student in _students)
|
@foreach (var student in _students)
|
||||||
{
|
{
|
||||||
<MudTh Style="width:120px; text-align:center;">
|
<MudTh Style="width:120px; text-align:center;">
|
||||||
@student.Name
|
@student.DisplayName
|
||||||
<MudTooltip Text="点击以切换此学生所有题目的对错">
|
<MudTooltip Text="点击以切换此学生所有题目的对错">
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Info" Size="Size.Small" Class="ml-1"
|
<MudIconButton Icon="@Icons.Material.Filled.Info" Size="Size.Small" Class="ml-1"
|
||||||
@onclick="() => ToggleStudentAllAnswers(student.Id)" />
|
@onclick="() => ToggleStudentAllAnswers(student.Id)" />
|
||||||
</MudTooltip>
|
</MudTooltip>
|
||||||
</MudTh>
|
</MudTh>
|
||||||
}
|
}
|
||||||
</HeaderContent>
|
</HeaderContent>
|
||||||
<RowTemplate>
|
<RowTemplate>
|
||||||
<MudTd DataLabel="序号">@context.QuestionItem.Sequence</MudTd>
|
<MudTd DataLabel="序号">@context.QuestionItem.Sequence</MudTd>
|
||||||
<MudTd DataLabel="分值" Style="text-align:center;">@context.QuestionItem.Score</MudTd>
|
<MudTd DataLabel="分值" Style="text-align:center;">@context.QuestionItem.Score</MudTd>
|
||||||
@foreach (var student in _students)
|
@foreach (var student in _students)
|
||||||
{
|
{
|
||||||
<MudTd DataLabel="@student.Name" Style="text-align:center;">
|
<MudTd DataLabel="@student.DisplayName" Style="text-align:center;">
|
||||||
@if (context.StudentAnswers.ContainsKey(student.Id))
|
@if (context.StudentAnswers.ContainsKey(student.Id))
|
||||||
{
|
{
|
||||||
<MudCheckBox @bind-Value="context.StudentAnswers[student.Id]" Size="Size.Small" Color="Color.Primary"></MudCheckBox>
|
<MudCheckBox @bind-Value="context.StudentAnswers[student.Id]" Size="Size.Small" Color="Color.Primary"></MudCheckBox>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<MudText Color="Color.Warning">N/A</MudText>
|
<MudText Color="Color.Warning">N/A</MudText>
|
||||||
}
|
}
|
||||||
</MudTd>
|
</MudTd>
|
||||||
}
|
}
|
||||||
</RowTemplate>
|
</RowTemplate>
|
||||||
<PagerContent>
|
<PagerContent>
|
||||||
<MudTablePager />
|
<MudTablePager />
|
||||||
</PagerContent>
|
</PagerContent>
|
||||||
</MudTable>
|
</MudTable>
|
||||||
|
|
||||||
<MudPaper Class="pa-4 mt-4 mud-elevation-2 d-flex flex-column align-end">
|
<MudPaper Class="pa-4 mt-4 mud-elevation-2 d-flex flex-column align-end">
|
||||||
<MudText Typo="Typo.h6">学生总分预览:</MudText>
|
<MudText Typo="Typo.h6">学生总分预览:</MudText>
|
||||||
@foreach (var student in _students)
|
@foreach (var student in _students)
|
||||||
{
|
{
|
||||||
<MudText Typo="Typo.subtitle1">
|
<MudText Typo="Typo.subtitle1">
|
||||||
@student.Name: <MudText Typo="Typo.h5" Color="Color.Primary" Class="d-inline-block ml-2">@GetStudentTotalScore(student.Id)</MudText>
|
@student.DisplayName: <MudText Typo="Typo.h5" Color="Color.Primary" Class="d-inline-block ml-2">@GetStudentTotalScore(student.Id)</MudText>
|
||||||
</MudText>
|
</MudText>
|
||||||
}
|
}
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Success" Class="mt-4" @onclick="SubmitGrading">
|
<MudButton Variant="Variant.Filled" Color="Color.Success" Class="mt-4" @onclick="SubmitGrading">
|
||||||
提交批改结果 (模拟)
|
提交批改结果 (模拟)
|
||||||
</MudButton>
|
</MudButton>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<MudAlert Severity="Severity.Info" Class="mt-4">无法加载试卷或题目信息。</MudAlert>
|
<MudAlert Severity="Severity.Info" Class="mt-4">无法加载试卷或题目信息。</MudAlert>
|
||||||
<MudButton Variant="Variant.Text" Color="Color.Primary" Class="mt-4" >返回试卷列表</MudButton>
|
<MudButton Variant="Variant.Text" Color="Color.Primary" Class="mt-4">返回试卷列表</MudButton>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string ExamId { get; set; }
|
public string ExamId { get; set; }
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
public IExamService ExamService { get; set; }
|
public IExamService ExamService { get; set; }
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
private ISnackbar Snackbar { get; set; }
|
private ISnackbar Snackbar { get; set; }
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
private NavigationManager Navigation { get; set; }
|
private NavigationManager Navigation { get; set; }
|
||||||
|
|
||||||
private MudTable<QuestionRowData> _table = new();
|
private MudTable<QuestionRowData> _table = new();
|
||||||
private AssignmentDto Assignment { get; set; } = new AssignmentDto();
|
private AssignmentDto Assignment { get; set; } = new AssignmentDto();
|
||||||
private ExamStruct _examStruct = new ExamStruct();
|
private AssignmentCheckData _examStruct = new AssignmentCheckData();
|
||||||
|
|
||||||
private List<Student> _students = new List<Student>();
|
private List<StudentDto> _students = new List<StudentDto>();
|
||||||
private List<QuestionRowData> _questionsForTable = new List<QuestionRowData>();
|
private List<QuestionRowData> _questionsForTable = new List<QuestionRowData>();
|
||||||
|
|
||||||
private bool _isLoading = true;
|
private bool _isLoading = true;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
public IClassServices ClassServices { get; set; }
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
_isLoading = true;
|
||||||
|
await LoadExamData();
|
||||||
|
|
||||||
|
var result = await ClassServices.GetClassStudents();
|
||||||
|
if (!result.Status) Snackbar.Add($"获取学生失败, {result.Message}", Severity.Error);
|
||||||
|
_students = result.Result as List<StudentDto> ?? new List<StudentDto>();
|
||||||
|
BuildTable();
|
||||||
|
_isLoading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildTable()
|
||||||
|
{
|
||||||
|
_questionsForTable = _examStruct.Questions.Select(q =>
|
||||||
|
{
|
||||||
|
var rowData = new QuestionRowData
|
||||||
|
{
|
||||||
|
QuestionItem = q,
|
||||||
|
StudentAnswers = new Dictionary<Guid, bool>()
|
||||||
|
};
|
||||||
|
foreach (var student in _students)
|
||||||
|
{
|
||||||
|
rowData.StudentAnswers[student.Id] = false;
|
||||||
|
}
|
||||||
|
return rowData;
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task LoadExamData()
|
||||||
|
{
|
||||||
|
if (Guid.TryParse(ExamId, out Guid parsedExamId))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await ExamService.GetExam(parsedExamId);
|
||||||
|
if (result.Status)
|
||||||
|
{
|
||||||
|
Assignment = result.Result as AssignmentDto ?? new AssignmentDto();
|
||||||
|
_examStruct = Assignment.GetStruct();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Snackbar?.Add($"获取试卷失败: {result.Message}", Severity.Error);
|
||||||
|
Navigation.NavigateTo("/exam/manager");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine($"获取试卷时发生错误: {ex.Message}");
|
||||||
|
Snackbar?.Add($"获取试卷失败: {ex.Message}", Severity.Error);
|
||||||
|
Navigation.NavigateTo("/exam/manager");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine($"错误:路由参数 ExamId '{ExamId}' 不是一个有效的 GUID 格式。");
|
||||||
|
Snackbar?.Add("无效的试卷ID,无法加载。", Severity.Error);
|
||||||
|
Navigation.NavigateTo("/exam/manager");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
private float GetStudentTotalScore(Guid studentId)
|
||||||
_isLoading = true;
|
{
|
||||||
await LoadExamData();
|
float totalScore = 0;
|
||||||
GenerateTemporaryStudentsAndAnswers();
|
foreach (var row in _questionsForTable)
|
||||||
_isLoading = false;
|
{
|
||||||
}
|
if (row.StudentAnswers.TryGetValue(studentId, out bool isCorrect) && isCorrect)
|
||||||
|
{
|
||||||
|
totalScore += row.QuestionItem.Score;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return totalScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ToggleStudentAllAnswers(Guid studentId)
|
||||||
|
{
|
||||||
|
bool allCorrect = _questionsForTable.All(row => row.StudentAnswers.ContainsKey(studentId) && row.StudentAnswers[studentId]);
|
||||||
|
|
||||||
|
foreach (var row in _questionsForTable)
|
||||||
|
{
|
||||||
|
if (row.StudentAnswers.ContainsKey(studentId))
|
||||||
|
{
|
||||||
|
row.StudentAnswers[studentId] = !allCorrect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SubmitGrading()
|
||||||
|
{
|
||||||
|
|
||||||
|
List<SubmissionDto> submissionDto = new List<SubmissionDto>();
|
||||||
|
|
||||||
|
|
||||||
private async Task LoadExamData()
|
foreach (var student in _students)
|
||||||
{
|
{
|
||||||
if (Guid.TryParse(ExamId, out Guid parsedExamId))
|
var newSubmission = new SubmissionDto();
|
||||||
{
|
newSubmission.StudentId = student.Id;
|
||||||
try
|
newSubmission.AssignmentId = Assignment.Id;
|
||||||
{
|
newSubmission.SubmissionTime = DateTime.Now;
|
||||||
var result = await ExamService.GetExam(parsedExamId);
|
newSubmission.Status = Entities.Contracts.SubmissionStatus.Submitted;
|
||||||
if (result.Status)
|
|
||||||
{
|
|
||||||
Assignment = result.Result as AssignmentDto ?? new AssignmentDto();
|
|
||||||
_examStruct = Assignment.GetStruct();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Snackbar?.Add($"获取试卷失败: {result.Message}", Severity.Error);
|
|
||||||
Navigation.NavigateTo("/exam/manager");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine($"获取试卷时发生错误: {ex.Message}");
|
|
||||||
Snackbar?.Add($"获取试卷失败: {ex.Message}", Severity.Error);
|
|
||||||
Navigation.NavigateTo("/exam/manager");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine($"错误:路由参数 ExamId '{ExamId}' 不是一个有效的 GUID 格式。");
|
|
||||||
Snackbar?.Add("无效的试卷ID,无法加载。", Severity.Error);
|
|
||||||
Navigation.NavigateTo("/exam/manager");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成临时学生和作答数据
|
|
||||||
private void GenerateTemporaryStudentsAndAnswers()
|
|
||||||
{
|
|
||||||
_students = new List<Student>();
|
|
||||||
// 生成 40 个学生
|
|
||||||
for (int i = 1; i <= 40; i++)
|
|
||||||
{
|
|
||||||
_students.Add(new Student { Name = $"学生{i}" });
|
|
||||||
}
|
|
||||||
|
|
||||||
_questionsForTable = _examStruct.Questions.Select(qItem =>
|
foreach (var row in _questionsForTable)
|
||||||
{
|
{
|
||||||
var rowData = new QuestionRowData
|
if (row.QuestionItem.AssignmentQuestionDto.StructType == Entities.Contracts.AssignmentStructType.Struct) continue;
|
||||||
{
|
if (row.StudentAnswers.TryGetValue(student.Id, out bool isCorrect))
|
||||||
QuestionItem = qItem,
|
{
|
||||||
StudentAnswers = new Dictionary<Guid, bool>()
|
newSubmission.SubmissionDetails.Add(new SubmissionDetailDto
|
||||||
};
|
{
|
||||||
|
IsCorrect = isCorrect,
|
||||||
|
StudentId = student.Id,
|
||||||
|
AssignmentQuestionId = row.QuestionItem.AssignmentQuestionDto.Id,
|
||||||
|
PointsAwarded = isCorrect ? row.QuestionItem.AssignmentQuestionDto.Score : 0
|
||||||
|
});
|
||||||
|
|
||||||
// 为每个学生随机生成初始的对错状态
|
newSubmission.OverallGrade += isCorrect ? row.QuestionItem.AssignmentQuestionDto.Score : 0;
|
||||||
var random = new Random();
|
}
|
||||||
foreach (var student in _students)
|
}
|
||||||
{
|
submissionDto.Add(newSubmission);
|
||||||
// 模拟随机对错,50%的概率
|
}
|
||||||
rowData.StudentAnswers[student.Id] = random.Next(0, 2) == 1;
|
|
||||||
}
|
|
||||||
return rowData;
|
|
||||||
}).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 当某个学生的某个题目的作答状态改变时触发
|
submissionDto.ForEach(async s =>
|
||||||
private void OnAnswerChanged(string questionSequence, Guid studentId, bool isCorrect)
|
{
|
||||||
{
|
Snackbar?.Add($"正在提交: {_students.FirstOrDefault(std => std.Id == s.StudentId)?.DisplayName} 的试卷", Severity.Info);
|
||||||
// 可以在这里添加额外的逻辑,例如记录更改
|
await ExamService.SubmissionAssignment(s);
|
||||||
Console.WriteLine($"题目 {questionSequence}, 学生 {studentId} 的答案变为: {isCorrect}");
|
});
|
||||||
// 由于是 @bind-Checked,数据模型已经自动更新,这里只是日志
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算某个学生的总分
|
|
||||||
private float GetStudentTotalScore(Guid studentId)
|
|
||||||
{
|
|
||||||
float totalScore = 0;
|
|
||||||
foreach (var row in _questionsForTable)
|
|
||||||
{
|
|
||||||
if (row.StudentAnswers.TryGetValue(studentId, out bool isCorrect) && isCorrect)
|
|
||||||
{
|
|
||||||
totalScore += row.QuestionItem.Score;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return totalScore;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 切换某个学生所有题目的对错状态 (用于快速批改)
|
|
||||||
private void ToggleStudentAllAnswers(Guid studentId)
|
|
||||||
{
|
|
||||||
bool allCorrect = _questionsForTable.All(row => row.StudentAnswers.ContainsKey(studentId) && row.StudentAnswers[studentId]);
|
|
||||||
|
|
||||||
foreach (var row in _questionsForTable)
|
Snackbar?.Add("批改结果已提交(模拟)", Severity.Success);
|
||||||
{
|
}
|
||||||
if (row.StudentAnswers.ContainsKey(studentId))
|
|
||||||
{
|
|
||||||
row.StudentAnswers[studentId] = !allCorrect; // 全部取反
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StateHasChanged(); // 手动通知 Blazor 刷新 UI
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提交批改结果(模拟)
|
|
||||||
private void SubmitGrading()
|
|
||||||
{
|
|
||||||
Console.WriteLine("--- 提交批改结果 ---");
|
|
||||||
foreach (var student in _students)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"学生: {student.Name}, 总分: {GetStudentTotalScore(student.Id)}");
|
|
||||||
foreach (var row in _questionsForTable)
|
|
||||||
{
|
|
||||||
if (row.StudentAnswers.TryGetValue(student.Id, out bool isCorrect))
|
|
||||||
{
|
|
||||||
Console.WriteLine($" - 题目 {row.QuestionItem.Sequence}: {(isCorrect ? "正确" : "错误")}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Snackbar?.Add("批改结果已提交(模拟)", Severity.Success);
|
|
||||||
// 实际应用中,这里会将 _questionsForTable 和 _students 的数据发送到后端API
|
|
||||||
}
|
|
||||||
}
|
}
|
@@ -49,7 +49,7 @@ else
|
|||||||
{
|
{
|
||||||
isloding = true;
|
isloding = true;
|
||||||
Snackbar.Add("正在加载", Severity.Info);
|
Snackbar.Add("正在加载", Severity.Info);
|
||||||
var result = await ExamService.GetAllExam(authenticationStateTask.Result.User.Identity.Name);
|
var result = await ExamService.GetAllExam();
|
||||||
examDtos = result.Result as List<AssignmentDto> ?? new List<AssignmentDto>();
|
examDtos = result.Result as List<AssignmentDto> ?? new List<AssignmentDto>();
|
||||||
isloding = false;
|
isloding = false;
|
||||||
Snackbar.Add("加载成功", Severity.Info);
|
Snackbar.Add("加载成功", Severity.Info);
|
||||||
|
@@ -12,7 +12,11 @@
|
|||||||
|
|
||||||
<MudButton OnClick="ExamClick"> 详情 </MudButton>
|
<MudButton OnClick="ExamClick"> 详情 </MudButton>
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Delete" aria-label="delete" />
|
<MudIconButton Icon="@Icons.Material.Filled.Delete" aria-label="delete" />
|
||||||
<MudIconButton Icon="@Icons.Custom.Brands.GitHub" OnClick="CheckExam" Color="Color.Primary" aria-label="github" />
|
@if (bteacher)
|
||||||
|
{
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Check" OnClick="CheckExam" Color="Color.Primary" aria-label="github" />
|
||||||
|
}
|
||||||
|
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Favorite" Color="Color.Secondary" aria-label="add to favorite" />
|
<MudIconButton Icon="@Icons.Material.Filled.Favorite" Color="Color.Secondary" aria-label="add to favorite" />
|
||||||
</MudButtonGroup>
|
</MudButtonGroup>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
@@ -21,6 +25,10 @@
|
|||||||
</MudPaper>
|
</MudPaper>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
[CascadingParameter]
|
||||||
|
private Task<AuthenticationState> authenticationStateTask { get; set; }
|
||||||
|
|
||||||
|
private bool bteacher = false;
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
public NavigationManager navigationManager { get; set; }
|
public NavigationManager navigationManager { get; set; }
|
||||||
@@ -45,6 +53,12 @@
|
|||||||
public string? MaxHeight { get; set; } = "64";
|
public string? MaxHeight { get; set; } = "64";
|
||||||
|
|
||||||
|
|
||||||
|
protected override Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
bteacher = authenticationStateTask.Result.User.IsInRole("Teacher");
|
||||||
|
return base.OnInitializedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
private void ExamClick()
|
private void ExamClick()
|
||||||
{
|
{
|
||||||
navigationManager.NavigateTo($"exam/edit/{AssignmentDto.Id}");
|
navigationManager.NavigateTo($"exam/edit/{AssignmentDto.Id}");
|
||||||
|
@@ -1,118 +1,10 @@
|
|||||||
@page "/"
|
@page "/"
|
||||||
@using Microsoft.AspNetCore.Authorization
|
@using Microsoft.AspNetCore.Authorization
|
||||||
|
|
||||||
<AuthorizeView Roles="Administrator">
|
<TechHelper.Client.Pages.Teacher.StudentsView/>
|
||||||
|
|
||||||
<MudText> Hello @context.User.Identity.Name</MudText>
|
|
||||||
@foreach (var item in context.User.Claims)
|
|
||||||
{
|
|
||||||
<MudPaper class="ma-2 pa-2">
|
|
||||||
<MudText> @item.Value </MudText>
|
|
||||||
<MudText> @item.Issuer </MudText>
|
|
||||||
<MudText> @item.Subject </MudText>
|
|
||||||
<MudText> @item.Properties </MudText>
|
|
||||||
<MudText> @item.ValueType </MudText>
|
|
||||||
</MudPaper>
|
|
||||||
}
|
|
||||||
|
|
||||||
Welcome to your new app.
|
@code {
|
||||||
</AuthorizeView>
|
[CascadingParameter]
|
||||||
|
private Task<AuthenticationState> authenticationStateTask { get; set; }
|
||||||
<MudText>Hello </MudText>
|
}
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
||||||
<MudText>Hello </MudText>
|
|
28
TechHelper.Client/Pages/Teacher/StudentsView.razor
Normal file
28
TechHelper.Client/Pages/Teacher/StudentsView.razor
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
@using Entities.Contracts
|
||||||
|
@using Entities.DTO
|
||||||
|
@using TechHelper.Client.Services
|
||||||
|
<h3>StudentsView</h3>
|
||||||
|
|
||||||
|
|
||||||
|
@foreach(var cs in ClassStudents)
|
||||||
|
{
|
||||||
|
<MudText> @cs.DisplayName </MudText>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[CascadingParameter]
|
||||||
|
private Task<AuthenticationState> authenticationStateTask { get; set; }
|
||||||
|
|
||||||
|
private List<StudentDto> ClassStudents { get; set; } = new List<StudentDto>();
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
public IClassServices ClassServices { get; set; }
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
var result = await ClassServices.GetClassStudents();
|
||||||
|
ClassStudents = result.Result as List<StudentDto> ?? new List<StudentDto>();
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,9 @@
|
|||||||
using Entities.DTO;
|
using Entities.Contracts;
|
||||||
|
using Entities.DTO;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using TechHelper.Client.HttpRepository;
|
using TechHelper.Client.HttpRepository;
|
||||||
|
using TechHelper.Services;
|
||||||
|
|
||||||
namespace TechHelper.Client.Services
|
namespace TechHelper.Client.Services
|
||||||
{
|
{
|
||||||
@@ -20,6 +23,21 @@ namespace TechHelper.Client.Services
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<ApiResponse> GetClassStudents()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await _client.PostAsJsonAsync("class/getClassStudents","");
|
||||||
|
var content = await result.Content.ReadAsStringAsync();
|
||||||
|
var users = JsonConvert.DeserializeObject<List<StudentDto>>(content);
|
||||||
|
return ApiResponse.Success(result: users);
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
return ApiResponse.Error($"获取失败,{ex.Message}, InnerException: {ex.InnerException}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<ResponseDto> UserRegister(UserRegistrationToClassDto userRegistrationToClassDto)
|
public async Task<ResponseDto> UserRegister(UserRegistrationToClassDto userRegistrationToClassDto)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@@ -9,13 +9,13 @@ namespace TechHelper.Client.Services
|
|||||||
{
|
{
|
||||||
public class ExamService : IExamService
|
public class ExamService : IExamService
|
||||||
{
|
{
|
||||||
private readonly IAIService _aIService;
|
private readonly IAIService _aIService;
|
||||||
private readonly HttpClient _client;
|
private readonly HttpClient _client;
|
||||||
|
|
||||||
public ExamService(IAIService aIService, HttpClient client)
|
public ExamService(IAIService aIService, HttpClient client)
|
||||||
{
|
{
|
||||||
_aIService = aIService;
|
_aIService = aIService;
|
||||||
_client = client;
|
_client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApiResponse ConvertToXML<T>(string xmlContent)
|
public ApiResponse ConvertToXML<T>(string xmlContent)
|
||||||
@@ -86,9 +86,9 @@ namespace TechHelper.Client.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ApiResponse> GetAllExam(string user)
|
public async Task<ApiResponse> GetAllExam()
|
||||||
{
|
{
|
||||||
var response = await _client.GetAsync($"exam/getAllPreview?user={user}");
|
var response = await _client.GetAsync($"exam/getAllPreview");
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
@@ -104,6 +104,25 @@ namespace TechHelper.Client.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<ApiResponse> GetAllSubmission()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await _client.GetAsync($"exam/getAllSubmission");
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
var exam = JsonConvert.DeserializeObject<AssignmentDto>(content);
|
||||||
|
return ApiResponse.Success();
|
||||||
|
}
|
||||||
|
return ApiResponse.Error(message: "获取失败");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return ApiResponse.Error(message: $"内部错误{ex.Message}, InerEx{ex.InnerException}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<ApiResponse> GetExam(Guid guid)
|
public async Task<ApiResponse> GetExam(Guid guid)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -158,5 +177,18 @@ namespace TechHelper.Client.Services
|
|||||||
return ApiResponse.Error(message: $"保存试题失败: {response.StatusCode} - {errorContent}");
|
return ApiResponse.Error(message: $"保存试题失败: {response.StatusCode} - {errorContent}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<ApiResponse> SubmissionAssignment(SubmissionDto submission)
|
||||||
|
{
|
||||||
|
var response = await _client.PostAsJsonAsync("exam/submission", submission);
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
return ApiResponse.Success("提交成功");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ApiResponse.Error("提交失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -8,5 +8,6 @@ namespace TechHelper.Client.Services
|
|||||||
{
|
{
|
||||||
public Task<ResponseDto> UserRegister(UserRegistrationToClassDto userRegistrationToClassDto);
|
public Task<ResponseDto> UserRegister(UserRegistrationToClassDto userRegistrationToClassDto);
|
||||||
public Task<ResponseDto> CreateClass(UserRegistrationToClassDto userClass);
|
public Task<ResponseDto> CreateClass(UserRegistrationToClassDto userClass);
|
||||||
|
public Task<ApiResponse> GetClassStudents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,9 @@ namespace TechHelper.Client.Services
|
|||||||
public Task<ApiResponse> ParseSingleQuestionGroup(string examContent);
|
public Task<ApiResponse> ParseSingleQuestionGroup(string examContent);
|
||||||
public ApiResponse ConvertToXML<T>(string xmlContent);
|
public ApiResponse ConvertToXML<T>(string xmlContent);
|
||||||
|
|
||||||
public Task<ApiResponse> GetAllExam(string user);
|
public Task<ApiResponse> GetAllExam();
|
||||||
public Task<ApiResponse> GetExam(Guid guid);
|
public Task<ApiResponse> GetExam(Guid guid);
|
||||||
|
public Task<ApiResponse> SubmissionAssignment(SubmissionDto submission);
|
||||||
|
public Task<ApiResponse> GetAllSubmission();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -36,20 +36,22 @@ namespace TechHelper.Context
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Assignment
|
||||||
|
CreateMap<AssignmentDto, Assignment>().ReverseMap();
|
||||||
|
|
||||||
CreateMap<Assignment, AssignmentDto>();
|
CreateMap<AssignmentQuestionDto, AssignmentQuestion>().ReverseMap();
|
||||||
|
|
||||||
|
CreateMap<QuestionDto, Question>().ReverseMap();
|
||||||
|
|
||||||
CreateMap<QuestionContext, QuestionContextDto>().ReverseMap();
|
CreateMap<QuestionContext, QuestionContextDto>().ReverseMap();
|
||||||
|
|
||||||
CreateMap<AssignmentQuestion, AssignmentQuestionDto>();
|
|
||||||
|
|
||||||
CreateMap<Question, QuestionDto>();
|
|
||||||
|
|
||||||
CreateMap<AssignmentDto, Assignment>();
|
|
||||||
|
|
||||||
CreateMap<AssignmentQuestionDto, AssignmentQuestion>();
|
// Submission
|
||||||
|
CreateMap<SubmissionDto, Submission>().ReverseMap();
|
||||||
|
|
||||||
CreateMap<QuestionDto, Question>();
|
CreateMap<SubmissionDetailDto, SubmissionDetail>().ReverseMap();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -57,26 +57,13 @@ namespace TechHelper.Context.Configuration
|
|||||||
.HasForeignKey(a => a.CreatorId)
|
.HasForeignKey(a => a.CreatorId)
|
||||||
.IsRequired(); // CreatedBy 是必填的,对应 [Required] 在外键属性上
|
.IsRequired(); // CreatedBy 是必填的,对应 [Required] 在外键属性上
|
||||||
|
|
||||||
// 关系: Assignment (一) 到 AssignmentClass (多)
|
|
||||||
// 假设 AssignmentClass 实体包含一个名为 AssignmentId 的外键属性
|
|
||||||
builder.HasMany(a => a.AssignmentClasses)
|
|
||||||
.WithOne(ac => ac.Assignment) // AssignmentClass 没有指向 Assignment 的导航属性 (或我们不知道)
|
|
||||||
.HasForeignKey("AssignmentId") // 指定外键名称为 AssignmentId
|
|
||||||
.OnDelete(DeleteBehavior.Cascade); // 如果 Assignment 被删除,关联的 AssignmentClass 也会被删除
|
|
||||||
|
|
||||||
// 关系: Assignment (一) 到 AssignmentAttachment (多)
|
|
||||||
// 假设 AssignmentAttachment 实体包含一个名为 AssignmentId 的外键属性
|
|
||||||
builder.HasMany(a => a.AssignmentAttachments)
|
|
||||||
.WithOne(aa => aa.Assignment)
|
|
||||||
.HasForeignKey("AssignmentId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
|
|
||||||
// 关系: Assignment (一) 到 Submission (多)
|
builder.HasOne(a=>a.ExamStruct)
|
||||||
// 假设 Submission 实体包含一个名为 AssignmentId 的外键属性
|
.WithOne()
|
||||||
builder.HasMany(a => a.Submissions)
|
.HasForeignKey<Assignment>(a=>a.ExamStructId)
|
||||||
.WithOne(s => s.Assignment)
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
.HasForeignKey("AssignmentId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -42,35 +42,24 @@ namespace TechHelper.Context.Configuration
|
|||||||
.HasColumnName("deleted")
|
.HasColumnName("deleted")
|
||||||
.HasDefaultValue(false); // 适用于软删除策略
|
.HasDefaultValue(false); // 适用于软删除策略
|
||||||
|
|
||||||
// 4. 配置导航属性和外键关系
|
|
||||||
|
|
||||||
// ---
|
builder.HasOne(aq => aq.Question)
|
||||||
// 配置 AssignmentQuestion 到 Question 的关系 (多对一)
|
.WithMany(q => q.AssignmentQuestions)
|
||||||
// 一个 AssignmentQuestion 属于一个 Question。
|
.HasForeignKey(aq => aq.QuestionId)
|
||||||
//
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
// 假设 `Question` 实体中有一个名为 `AssignmentQuestions` 的 `ICollection<AssignmentQuestion>` 集合属性。
|
|
||||||
builder.HasOne(aq => aq.Question) // 当前 AssignmentQuestion 有一个 Question
|
|
||||||
.WithMany(q => q.AssignmentQuestions) // 那个 Question 可以有多个 AssignmentQuestion
|
|
||||||
.HasForeignKey(aq => aq.QuestionId) // 外键是 AssignmentQuestion.QuestionId
|
|
||||||
.OnDelete(DeleteBehavior.Cascade); // 当 Question 被删除时,相关的 AssignmentQuestion 也级联删除。
|
|
||||||
|
|
||||||
|
builder.HasOne(aq => aq.ParentAssignmentQuestion)
|
||||||
|
.WithMany(aq => aq.ChildrenAssignmentQuestion)
|
||||||
|
.HasForeignKey(aq => aq.ParentAssignmentQuestionId)
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
builder.HasOne(aq => aq.QuestionContext)
|
builder.HasOne(aq => aq.QuestionContext)
|
||||||
.WithMany(qc => qc.Questions)
|
.WithMany(qc => qc.Questions)
|
||||||
.HasForeignKey(aq => aq.QuestionContextId)
|
.HasForeignKey(aq => aq.QuestionContextId)
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
|
||||||
// ---
|
|
||||||
// 配置 AssignmentQuestion 到 SubmissionDetail 的关系 (一对多)
|
|
||||||
// 一个 AssignmentQuestion 可以有多个 SubmissionDetail。
|
|
||||||
//
|
|
||||||
// 这个关系通常从 "多" 的一方(`SubmissionDetail` 实体)来配置外键。
|
|
||||||
// 假设 `SubmissionDetail` 实体有一个 `AssignmentQuestionId` 外键和 `AssignmentQuestion` 导航属性。
|
|
||||||
builder.HasMany(aq => aq.SubmissionDetails) // 当前 AssignmentQuestion 有多个 SubmissionDetail
|
|
||||||
.WithOne(sd => sd.AssignmentQuestion); // 每一个 SubmissionDetail 都有一个 AssignmentQuestion
|
|
||||||
// .HasForeignKey(sd => sd.AssignmentQuestionId); // 外键的配置应在 `SubmissionDetailConfiguration` 中进行
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -75,16 +75,13 @@ namespace TechHelper.Context.Configuration
|
|||||||
builder.HasOne(s => s.Student) // 当前 Submission 有一个 Student (User)
|
builder.HasOne(s => s.Student) // 当前 Submission 有一个 Student (User)
|
||||||
.WithMany(u => u.SubmissionsAsStudent) // 那个 User (Student) 可以有多个 Submission
|
.WithMany(u => u.SubmissionsAsStudent) // 那个 User (Student) 可以有多个 Submission
|
||||||
.HasForeignKey(s => s.StudentId) // 外键是 Submission.StudentId
|
.HasForeignKey(s => s.StudentId) // 外键是 Submission.StudentId
|
||||||
.OnDelete(DeleteBehavior.Restrict); // 当 User (Student) 被删除时,如果还有其提交的 Submission,则会阻止删除。
|
.OnDelete(DeleteBehavior.Cascade); // 当 User (Student) 被删除时,如果还有其提交的 Submission,则会阻止删除。
|
||||||
|
|
||||||
builder.HasOne(s => s.Grader) // 当前 Submission 有一个 Grader (User),可以是空的
|
builder.HasOne(s => s.Grader) // 当前 Submission 有一个 Grader (User),可以是空的
|
||||||
.WithMany(u => u.GradedSubmissions) // 那个 User (Grader) 可以批改多个 Submission
|
.WithMany(u => u.GradedSubmissions) // 那个 User (Grader) 可以批改多个 Submission
|
||||||
.HasForeignKey(s => s.GraderId) // 外键是 Submission.GradedBy
|
.HasForeignKey(s => s.GraderId) // 外键是 Submission.GradedBy
|
||||||
.OnDelete(DeleteBehavior.SetNull); // 当 User (Grader) 被删除时,如果 GradedBy 是可空的,则将其设置为 NULL。
|
.OnDelete(DeleteBehavior.SetNull); // 当 User (Grader) 被删除时,如果 GradedBy 是可空的,则将其设置为 NULL。
|
||||||
|
|
||||||
|
|
||||||
builder.HasMany(s => s.SubmissionDetails) // 当前 Submission 有多个 SubmissionDetail
|
|
||||||
.WithOne(sd => sd.Submission); // 每一个 SubmissionDetail 都有一个 Submission
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -64,7 +64,7 @@ namespace TechHelper.Context.Configuration
|
|||||||
builder.HasOne(sd => sd.Student) // 当前 SubmissionDetail 有一个 User (作为学生)
|
builder.HasOne(sd => sd.Student) // 当前 SubmissionDetail 有一个 User (作为学生)
|
||||||
.WithMany(u => u.SubmissionDetails)
|
.WithMany(u => u.SubmissionDetails)
|
||||||
.HasForeignKey(sd => sd.StudentId) // 外键是 SubmissionDetail.StudentId
|
.HasForeignKey(sd => sd.StudentId) // 外键是 SubmissionDetail.StudentId
|
||||||
.OnDelete(DeleteBehavior.Restrict); // 当 User (学生) 被删除时,如果他/她还有提交详情,则会阻止删除。
|
.OnDelete(DeleteBehavior.Cascade); // 当 User (学生) 被删除时,如果他/她还有提交详情,则会阻止删除。
|
||||||
// 这是一个更安全的选择,以防止意外数据丢失。
|
// 这是一个更安全的选择,以防止意外数据丢失。
|
||||||
|
|
||||||
builder.HasOne(sd => sd.AssignmentQuestion) // 当前 SubmissionDetail 有一个 AssignmentQuestion
|
builder.HasOne(sd => sd.AssignmentQuestion) // 当前 SubmissionDetail 有一个 AssignmentQuestion
|
||||||
|
@@ -1,7 +1,10 @@
|
|||||||
using Entities.DTO;
|
using Entities.Contracts;
|
||||||
|
using Entities.DTO;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Security.Claims;
|
||||||
using TechHelper.Services;
|
using TechHelper.Services;
|
||||||
|
|
||||||
namespace TechHelper.Server.Controllers
|
namespace TechHelper.Server.Controllers
|
||||||
@@ -11,25 +14,76 @@ namespace TechHelper.Server.Controllers
|
|||||||
public class ClassController : ControllerBase
|
public class ClassController : ControllerBase
|
||||||
{
|
{
|
||||||
private IClassService _classService;
|
private IClassService _classService;
|
||||||
|
private UserManager<User> _userManager;
|
||||||
public ClassController(IClassService classService)
|
public ClassController(IClassService classService, UserManager<User> userManager)
|
||||||
{
|
{
|
||||||
_classService = classService;
|
_classService = classService;
|
||||||
|
_userManager = userManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("userRegiste")]
|
[HttpPost("userRegiste")]
|
||||||
public async Task<IActionResult> UserRegisterToClass(
|
public async Task<IActionResult> UserRegisterToClass(
|
||||||
[FromBody] UserRegistrationToClassDto toClass)
|
[FromBody] UserRegistrationToClassDto toClass)
|
||||||
{
|
{
|
||||||
|
|
||||||
var result = await _classService.UserRegister(toClass);
|
var result = await _classService.UserRegister(toClass);
|
||||||
|
|
||||||
if(!result.Status) return BadRequest(result.Message);
|
if (!result.Status) return BadRequest(result.Message);
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[HttpPost("getClassStudents")]
|
||||||
|
public async Task<IActionResult> GetClassStudents()
|
||||||
|
{
|
||||||
|
if (User.IsInRole("Teacher"))
|
||||||
|
{
|
||||||
|
var gradeClaim = User.FindFirst("Grade")?.Value;
|
||||||
|
var classClaim = User.FindFirst("Class")?.Value;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(gradeClaim) || string.IsNullOrEmpty(classClaim))
|
||||||
|
{
|
||||||
|
return BadRequest("未识别到你加入的班级信息(年级或班级声明缺失)。");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!byte.TryParse(gradeClaim, out byte grade) || !byte.TryParse(classClaim, out byte cla))
|
||||||
|
{
|
||||||
|
return BadRequest("你班级或年级信息格式不正确。");
|
||||||
|
}
|
||||||
|
|
||||||
|
var classDto = new ClassDto
|
||||||
|
{
|
||||||
|
Grade = grade,
|
||||||
|
Class = cla
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = await _classService.GetClassStudents(classDto);
|
||||||
|
var css = result.Result as ICollection<ClassStudent>;
|
||||||
|
if(css == null) return BadRequest("你还没有学生");
|
||||||
|
|
||||||
|
|
||||||
|
List<StudentDto> sts = new List<StudentDto>();
|
||||||
|
css?.ToList().ForEach(s => sts.Add(new StudentDto
|
||||||
|
{
|
||||||
|
DisplayName = s.Student.DisplayName,
|
||||||
|
Id = s.Student.Id,
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!result.Status)
|
||||||
|
{
|
||||||
|
return BadRequest(result.Message);
|
||||||
|
}
|
||||||
|
return Ok(sts);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return BadRequest("你没有权限查看,未识别到你的教师身份。");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPost("Create")]
|
[HttpPost("Create")]
|
||||||
public async Task<IActionResult> Create(
|
public async Task<IActionResult> Create(
|
||||||
[FromBody] ClassDto classDto)
|
[FromBody] ClassDto classDto)
|
||||||
|
@@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Identity;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using TechHelper.Server.Services;
|
using TechHelper.Server.Services;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
using TechHelper.Services;
|
||||||
|
|
||||||
|
|
||||||
namespace TechHelper.Server.Controllers
|
namespace TechHelper.Server.Controllers
|
||||||
@@ -31,7 +32,7 @@ namespace TechHelper.Server.Controllers
|
|||||||
[FromBody] AssignmentDto examDto)
|
[FromBody] AssignmentDto examDto)
|
||||||
{
|
{
|
||||||
var user = await _userManager.FindByEmailAsync(User.Identity?.Name ?? "");
|
var user = await _userManager.FindByEmailAsync(User.Identity?.Name ?? "");
|
||||||
if(user == null) return BadRequest("无效的用户");
|
if (user == null) return BadRequest("无效的用户");
|
||||||
|
|
||||||
examDto.CreatorId = user.Id;
|
examDto.CreatorId = user.Id;
|
||||||
var result = await _examService.CreateExamAsync(examDto);
|
var result = await _examService.CreateExamAsync(examDto);
|
||||||
@@ -45,6 +46,29 @@ namespace TechHelper.Server.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("submission")]
|
||||||
|
public async Task<IActionResult> SubmissionAssignment(
|
||||||
|
[FromBody] SubmissionDto submissionDto)
|
||||||
|
{
|
||||||
|
if (User == null) return BadRequest("无效的用户");
|
||||||
|
if (User.IsInRole("Teacher"))
|
||||||
|
{
|
||||||
|
var result = await _examService.SubmissionAssignment(submissionDto);
|
||||||
|
if (result.Status)
|
||||||
|
{
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return BadRequest(result.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return BadRequest("你没有权限修改");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet("get")]
|
[HttpGet("get")]
|
||||||
public async Task<IActionResult> GetExamById(Guid id)
|
public async Task<IActionResult> GetExamById(Guid id)
|
||||||
{
|
{
|
||||||
@@ -58,16 +82,26 @@ namespace TechHelper.Server.Controllers
|
|||||||
|
|
||||||
|
|
||||||
[HttpGet("getAllPreview")]
|
[HttpGet("getAllPreview")]
|
||||||
public async Task<IActionResult> GetAllExamPreview(string user)
|
public async Task<IActionResult> GetAllExamPreview()
|
||||||
{
|
{
|
||||||
string? userId = User.Identity.Name;
|
if (User == null) return BadRequest("用户验证失败, 无效用户");
|
||||||
|
|
||||||
var userid = await _userManager.FindByEmailAsync(user);
|
var userid = await _userManager.FindByEmailAsync(User.Identity.Name);
|
||||||
if (userid == null) return BadRequest("用户验证失败, 无效用户");
|
|
||||||
|
|
||||||
|
|
||||||
|
var result = new ApiResponse();
|
||||||
var result = await _examService.GetAllExamPreviewsAsync(userid.Id);
|
if (User.IsInRole("Teacher"))
|
||||||
|
{
|
||||||
|
result = await _examService.GetAllExamPreviewsAsync(userid.Id);
|
||||||
|
}
|
||||||
|
else if (User.IsInRole("Student"))
|
||||||
|
{
|
||||||
|
result = await _examService.GetAllSubmissionAsync(userid.Id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return BadRequest("你没有相应的权限");
|
||||||
|
}
|
||||||
|
|
||||||
if (result.Status)
|
if (result.Status)
|
||||||
{
|
{
|
||||||
@@ -76,5 +110,34 @@ namespace TechHelper.Server.Controllers
|
|||||||
return BadRequest(result);
|
return BadRequest(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[HttpGet("getAllSubmission")]
|
||||||
|
public async Task<IActionResult> GetAllSubmission()
|
||||||
|
{
|
||||||
|
if (User == null) return BadRequest("用户验证失败, 无效用户");
|
||||||
|
|
||||||
|
var userid = await _userManager.FindByEmailAsync(User.Identity.Name);
|
||||||
|
|
||||||
|
var result = await _examService.GetAllSubmissionAsync(userid.Id);
|
||||||
|
|
||||||
|
if (result.Status)
|
||||||
|
{
|
||||||
|
return Ok(result.Result);
|
||||||
|
}
|
||||||
|
return BadRequest(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Authorize(Roles = "Teacher")]
|
||||||
|
[HttpDelete("{guid}")]
|
||||||
|
public async Task<IActionResult> DeleteAsync(Guid guid)
|
||||||
|
{
|
||||||
|
var deleteResult = await _examService.DeleteAsync(guid);
|
||||||
|
if (deleteResult.Status)
|
||||||
|
{
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
return BadRequest();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
30
TechHelper.Server/Controllers/UserController.cs
Normal file
30
TechHelper.Server/Controllers/UserController.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using Entities.Contracts;
|
||||||
|
using Entities.DTO;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using TechHelper.Services;
|
||||||
|
|
||||||
|
namespace TechHelper.Server.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/user")]
|
||||||
|
[ApiController]
|
||||||
|
public class UserController : ControllerBase
|
||||||
|
{
|
||||||
|
private IClassService _classService;
|
||||||
|
private UserManager<User> _userManager;
|
||||||
|
public UserController(IClassService classService, UserManager<User> userManager)
|
||||||
|
{
|
||||||
|
_classService = classService;
|
||||||
|
_userManager = userManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[HttpPost("get")]
|
||||||
|
public async Task<IActionResult> GetAsync(
|
||||||
|
[FromBody] UserRegistrationToClassDto toClass)
|
||||||
|
{
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,95 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
|
|
||||||
|
|
||||||
namespace TechHelper.Server.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class up : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_class_teachers_AspNetUsers_teacher_id",
|
|
||||||
table: "class_teachers");
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "AspNetRoles",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("8b814a50-fd96-4bfa-a666-b247c0f13e22"));
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "AspNetRoles",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("ab2c8f8c-1ade-4ff5-9eb4-2925a89567b1"));
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "AspNetRoles",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("c6f92bbf-190f-47a5-b4d6-ed6874a378e8"));
|
|
||||||
|
|
||||||
migrationBuilder.InsertData(
|
|
||||||
table: "AspNetRoles",
|
|
||||||
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
|
|
||||||
values: new object[,]
|
|
||||||
{
|
|
||||||
{ new Guid("195b19c5-fd30-455c-9f38-9842b44bf5c3"), null, "Teacher", "TEACHER" },
|
|
||||||
{ new Guid("53cc63db-74bc-47a8-b71a-7e120d4018a9"), null, "Administrator", "ADMINISTRATOR" },
|
|
||||||
{ new Guid("a203eb76-97f0-418f-bc06-9549297d2ac3"), null, "Student", "STUDENT" }
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_class_teachers_AspNetUsers_teacher_id",
|
|
||||||
table: "class_teachers",
|
|
||||||
column: "teacher_id",
|
|
||||||
principalTable: "AspNetUsers",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_class_teachers_AspNetUsers_teacher_id",
|
|
||||||
table: "class_teachers");
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "AspNetRoles",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("195b19c5-fd30-455c-9f38-9842b44bf5c3"));
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "AspNetRoles",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("53cc63db-74bc-47a8-b71a-7e120d4018a9"));
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "AspNetRoles",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("a203eb76-97f0-418f-bc06-9549297d2ac3"));
|
|
||||||
|
|
||||||
migrationBuilder.InsertData(
|
|
||||||
table: "AspNetRoles",
|
|
||||||
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
|
|
||||||
values: new object[,]
|
|
||||||
{
|
|
||||||
{ new Guid("8b814a50-fd96-4bfa-a666-b247c0f13e22"), null, "Administrator", "ADMINISTRATOR" },
|
|
||||||
{ new Guid("ab2c8f8c-1ade-4ff5-9eb4-2925a89567b1"), null, "Student", "STUDENT" },
|
|
||||||
{ new Guid("c6f92bbf-190f-47a5-b4d6-ed6874a378e8"), null, "Teacher", "TEACHER" }
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_class_teachers_AspNetUsers_teacher_id",
|
|
||||||
table: "class_teachers",
|
|
||||||
column: "teacher_id",
|
|
||||||
principalTable: "AspNetUsers",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -12,8 +12,8 @@ using TechHelper.Context;
|
|||||||
namespace TechHelper.Server.Migrations
|
namespace TechHelper.Server.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(ApplicationContext))]
|
[DbContext(typeof(ApplicationContext))]
|
||||||
[Migration("20250625032845_up")]
|
[Migration("20250626073834_init")]
|
||||||
partial class up
|
partial class init
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
@@ -512,7 +512,6 @@ namespace TechHelper.Server.Migrations
|
|||||||
.HasColumnName("deleted");
|
.HasColumnName("deleted");
|
||||||
|
|
||||||
b.Property<string>("OverallFeedback")
|
b.Property<string>("OverallFeedback")
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("longtext")
|
.HasColumnType("longtext")
|
||||||
.HasColumnName("overall_feedback");
|
.HasColumnName("overall_feedback");
|
||||||
|
|
||||||
@@ -579,7 +578,6 @@ namespace TechHelper.Server.Migrations
|
|||||||
.HasColumnName("points_awarded");
|
.HasColumnName("points_awarded");
|
||||||
|
|
||||||
b.Property<string>("StudentAnswer")
|
b.Property<string>("StudentAnswer")
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("longtext")
|
.HasColumnType("longtext")
|
||||||
.HasColumnName("student_answer");
|
.HasColumnName("student_answer");
|
||||||
|
|
||||||
@@ -592,7 +590,6 @@ namespace TechHelper.Server.Migrations
|
|||||||
.HasColumnName("submission_id");
|
.HasColumnName("submission_id");
|
||||||
|
|
||||||
b.Property<string>("TeacherFeedback")
|
b.Property<string>("TeacherFeedback")
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("longtext")
|
.HasColumnType("longtext")
|
||||||
.HasColumnName("teacher_feedback");
|
.HasColumnName("teacher_feedback");
|
||||||
|
|
||||||
@@ -747,19 +744,19 @@ namespace TechHelper.Server.Migrations
|
|||||||
b.HasData(
|
b.HasData(
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("a203eb76-97f0-418f-bc06-9549297d2ac3"),
|
Id = new Guid("3cfe35e8-73d5-4170-9856-f1d078554822"),
|
||||||
Name = "Student",
|
Name = "Student",
|
||||||
NormalizedName = "STUDENT"
|
NormalizedName = "STUDENT"
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("195b19c5-fd30-455c-9f38-9842b44bf5c3"),
|
Id = new Guid("754c4967-6af2-4a81-b970-1e90a3a269b3"),
|
||||||
Name = "Teacher",
|
Name = "Teacher",
|
||||||
NormalizedName = "TEACHER"
|
NormalizedName = "TEACHER"
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("53cc63db-74bc-47a8-b71a-7e120d4018a9"),
|
Id = new Guid("8546457c-185c-4b79-bece-bc21e41d02e7"),
|
||||||
Name = "Administrator",
|
Name = "Administrator",
|
||||||
NormalizedName = "ADMINISTRATOR"
|
NormalizedName = "ADMINISTRATOR"
|
||||||
});
|
});
|
@@ -323,7 +323,7 @@ namespace TechHelper.Server.Migrations
|
|||||||
column: x => x.teacher_id,
|
column: x => x.teacher_id,
|
||||||
principalTable: "AspNetUsers",
|
principalTable: "AspNetUsers",
|
||||||
principalColumn: "Id",
|
principalColumn: "Id",
|
||||||
onDelete: ReferentialAction.Restrict);
|
onDelete: ReferentialAction.Cascade);
|
||||||
table.ForeignKey(
|
table.ForeignKey(
|
||||||
name: "FK_class_teachers_classes_class_id",
|
name: "FK_class_teachers_classes_class_id",
|
||||||
column: x => x.class_id,
|
column: x => x.class_id,
|
||||||
@@ -565,7 +565,7 @@ namespace TechHelper.Server.Migrations
|
|||||||
attempt_number = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
attempt_number = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
submission_time = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
submission_time = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||||
overall_grade = table.Column<float>(type: "float", precision: 5, scale: 2, nullable: true),
|
overall_grade = table.Column<float>(type: "float", precision: 5, scale: 2, nullable: true),
|
||||||
overall_feedback = table.Column<string>(type: "longtext", nullable: false)
|
overall_feedback = table.Column<string>(type: "longtext", nullable: true)
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
graded_by = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
|
graded_by = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
|
||||||
graded_at = table.Column<DateTime>(type: "datetime(6)", nullable: true),
|
graded_at = table.Column<DateTime>(type: "datetime(6)", nullable: true),
|
||||||
@@ -604,11 +604,11 @@ namespace TechHelper.Server.Migrations
|
|||||||
submission_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
submission_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
student_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
student_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
assignment_question_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
assignment_question_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
student_answer = table.Column<string>(type: "longtext", nullable: false)
|
student_answer = table.Column<string>(type: "longtext", nullable: true)
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
is_correct = table.Column<bool>(type: "tinyint(1)", nullable: true),
|
is_correct = table.Column<bool>(type: "tinyint(1)", nullable: true),
|
||||||
points_awarded = table.Column<float>(type: "float", precision: 5, scale: 2, nullable: true),
|
points_awarded = table.Column<float>(type: "float", precision: 5, scale: 2, nullable: true),
|
||||||
teacher_feedback = table.Column<string>(type: "longtext", nullable: false)
|
teacher_feedback = table.Column<string>(type: "longtext", nullable: true)
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
created_at = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
created_at = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
@@ -644,9 +644,9 @@ namespace TechHelper.Server.Migrations
|
|||||||
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
|
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
|
||||||
values: new object[,]
|
values: new object[,]
|
||||||
{
|
{
|
||||||
{ new Guid("8b814a50-fd96-4bfa-a666-b247c0f13e22"), null, "Administrator", "ADMINISTRATOR" },
|
{ new Guid("3cfe35e8-73d5-4170-9856-f1d078554822"), null, "Student", "STUDENT" },
|
||||||
{ new Guid("ab2c8f8c-1ade-4ff5-9eb4-2925a89567b1"), null, "Student", "STUDENT" },
|
{ new Guid("754c4967-6af2-4a81-b970-1e90a3a269b3"), null, "Teacher", "TEACHER" },
|
||||||
{ new Guid("c6f92bbf-190f-47a5-b4d6-ed6874a378e8"), null, "Teacher", "TEACHER" }
|
{ new Guid("8546457c-185c-4b79-bece-bc21e41d02e7"), null, "Administrator", "ADMINISTRATOR" }
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
@@ -12,8 +12,8 @@ using TechHelper.Context;
|
|||||||
namespace TechHelper.Server.Migrations
|
namespace TechHelper.Server.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(ApplicationContext))]
|
[DbContext(typeof(ApplicationContext))]
|
||||||
[Migration("20250624103910_init")]
|
[Migration("20250627101025_upd")]
|
||||||
partial class init
|
partial class upd
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
@@ -198,6 +198,11 @@ namespace TechHelper.Server.Migrations
|
|||||||
.HasColumnType("float")
|
.HasColumnType("float")
|
||||||
.HasColumnName("score");
|
.HasColumnName("score");
|
||||||
|
|
||||||
|
b.Property<string>("Sequence")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext")
|
||||||
|
.HasColumnName("sequence");
|
||||||
|
|
||||||
b.Property<byte>("StructType")
|
b.Property<byte>("StructType")
|
||||||
.HasColumnType("tinyint unsigned")
|
.HasColumnType("tinyint unsigned")
|
||||||
.HasColumnName("group_state");
|
.HasColumnName("group_state");
|
||||||
@@ -512,7 +517,6 @@ namespace TechHelper.Server.Migrations
|
|||||||
.HasColumnName("deleted");
|
.HasColumnName("deleted");
|
||||||
|
|
||||||
b.Property<string>("OverallFeedback")
|
b.Property<string>("OverallFeedback")
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("longtext")
|
.HasColumnType("longtext")
|
||||||
.HasColumnName("overall_feedback");
|
.HasColumnName("overall_feedback");
|
||||||
|
|
||||||
@@ -579,7 +583,6 @@ namespace TechHelper.Server.Migrations
|
|||||||
.HasColumnName("points_awarded");
|
.HasColumnName("points_awarded");
|
||||||
|
|
||||||
b.Property<string>("StudentAnswer")
|
b.Property<string>("StudentAnswer")
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("longtext")
|
.HasColumnType("longtext")
|
||||||
.HasColumnName("student_answer");
|
.HasColumnName("student_answer");
|
||||||
|
|
||||||
@@ -592,7 +595,6 @@ namespace TechHelper.Server.Migrations
|
|||||||
.HasColumnName("submission_id");
|
.HasColumnName("submission_id");
|
||||||
|
|
||||||
b.Property<string>("TeacherFeedback")
|
b.Property<string>("TeacherFeedback")
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("longtext")
|
.HasColumnType("longtext")
|
||||||
.HasColumnName("teacher_feedback");
|
.HasColumnName("teacher_feedback");
|
||||||
|
|
||||||
@@ -747,19 +749,19 @@ namespace TechHelper.Server.Migrations
|
|||||||
b.HasData(
|
b.HasData(
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("ab2c8f8c-1ade-4ff5-9eb4-2925a89567b1"),
|
Id = new Guid("c310acf7-9605-4c55-8b9f-9bf9cd2dadb9"),
|
||||||
Name = "Student",
|
Name = "Student",
|
||||||
NormalizedName = "STUDENT"
|
NormalizedName = "STUDENT"
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("c6f92bbf-190f-47a5-b4d6-ed6874a378e8"),
|
Id = new Guid("5f0c1b3c-ad05-4ca9-b9fd-a359cb518236"),
|
||||||
Name = "Teacher",
|
Name = "Teacher",
|
||||||
NormalizedName = "TEACHER"
|
NormalizedName = "TEACHER"
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("8b814a50-fd96-4bfa-a666-b247c0f13e22"),
|
Id = new Guid("a81f5de2-9691-45fa-8d31-ae4ffeb34453"),
|
||||||
Name = "Administrator",
|
Name = "Administrator",
|
||||||
NormalizedName = "ADMINISTRATOR"
|
NormalizedName = "ADMINISTRATOR"
|
||||||
});
|
});
|
||||||
@@ -925,7 +927,8 @@ namespace TechHelper.Server.Migrations
|
|||||||
{
|
{
|
||||||
b.HasOne("Entities.Contracts.AssignmentQuestion", "ParentAssignmentQuestion")
|
b.HasOne("Entities.Contracts.AssignmentQuestion", "ParentAssignmentQuestion")
|
||||||
.WithMany("ChildrenAssignmentQuestion")
|
.WithMany("ChildrenAssignmentQuestion")
|
||||||
.HasForeignKey("ParentAssignmentQuestionId");
|
.HasForeignKey("ParentAssignmentQuestionId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
b.HasOne("Entities.Contracts.QuestionContext", "QuestionContext")
|
b.HasOne("Entities.Contracts.QuestionContext", "QuestionContext")
|
||||||
.WithMany("Questions")
|
.WithMany("Questions")
|
||||||
@@ -985,7 +988,7 @@ namespace TechHelper.Server.Migrations
|
|||||||
b.HasOne("Entities.Contracts.User", "Teacher")
|
b.HasOne("Entities.Contracts.User", "Teacher")
|
||||||
.WithMany("TaughtClassesLink")
|
.WithMany("TaughtClassesLink")
|
||||||
.HasForeignKey("TeacherId")
|
.HasForeignKey("TeacherId")
|
||||||
.OnDelete(DeleteBehavior.Restrict)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.Navigation("Class");
|
b.Navigation("Class");
|
||||||
@@ -1067,7 +1070,7 @@ namespace TechHelper.Server.Migrations
|
|||||||
b.HasOne("Entities.Contracts.User", "Student")
|
b.HasOne("Entities.Contracts.User", "Student")
|
||||||
.WithMany("SubmissionsAsStudent")
|
.WithMany("SubmissionsAsStudent")
|
||||||
.HasForeignKey("StudentId")
|
.HasForeignKey("StudentId")
|
||||||
.OnDelete(DeleteBehavior.Restrict)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.Navigation("Assignment");
|
b.Navigation("Assignment");
|
||||||
@@ -1088,7 +1091,7 @@ namespace TechHelper.Server.Migrations
|
|||||||
b.HasOne("Entities.Contracts.User", "Student")
|
b.HasOne("Entities.Contracts.User", "Student")
|
||||||
.WithMany("SubmissionDetails")
|
.WithMany("SubmissionDetails")
|
||||||
.HasForeignKey("StudentId")
|
.HasForeignKey("StudentId")
|
||||||
.OnDelete(DeleteBehavior.Restrict)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.HasOne("Entities.Contracts.Submission", "Submission")
|
b.HasOne("Entities.Contracts.Submission", "Submission")
|
153
TechHelper.Server/Migrations/20250627101025_upd.cs
Normal file
153
TechHelper.Server/Migrations/20250627101025_upd.cs
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
|
||||||
|
|
||||||
|
namespace TechHelper.Server.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class upd : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_assignment_questions_assignment_questions_parent_question_gr~",
|
||||||
|
table: "assignment_questions");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_submission_details_AspNetUsers_student_id",
|
||||||
|
table: "submission_details");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_submissions_AspNetUsers_student_id",
|
||||||
|
table: "submissions");
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("3cfe35e8-73d5-4170-9856-f1d078554822"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("754c4967-6af2-4a81-b970-1e90a3a269b3"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("8546457c-185c-4b79-bece-bc21e41d02e7"));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "sequence",
|
||||||
|
table: "assignment_questions",
|
||||||
|
type: "longtext",
|
||||||
|
nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ new Guid("5f0c1b3c-ad05-4ca9-b9fd-a359cb518236"), null, "Teacher", "TEACHER" },
|
||||||
|
{ new Guid("a81f5de2-9691-45fa-8d31-ae4ffeb34453"), null, "Administrator", "ADMINISTRATOR" },
|
||||||
|
{ new Guid("c310acf7-9605-4c55-8b9f-9bf9cd2dadb9"), null, "Student", "STUDENT" }
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_assignment_questions_assignment_questions_parent_question_gr~",
|
||||||
|
table: "assignment_questions",
|
||||||
|
column: "parent_question_group_id",
|
||||||
|
principalTable: "assignment_questions",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_submission_details_AspNetUsers_student_id",
|
||||||
|
table: "submission_details",
|
||||||
|
column: "student_id",
|
||||||
|
principalTable: "AspNetUsers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_submissions_AspNetUsers_student_id",
|
||||||
|
table: "submissions",
|
||||||
|
column: "student_id",
|
||||||
|
principalTable: "AspNetUsers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_assignment_questions_assignment_questions_parent_question_gr~",
|
||||||
|
table: "assignment_questions");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_submission_details_AspNetUsers_student_id",
|
||||||
|
table: "submission_details");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_submissions_AspNetUsers_student_id",
|
||||||
|
table: "submissions");
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("5f0c1b3c-ad05-4ca9-b9fd-a359cb518236"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("a81f5de2-9691-45fa-8d31-ae4ffeb34453"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("c310acf7-9605-4c55-8b9f-9bf9cd2dadb9"));
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "sequence",
|
||||||
|
table: "assignment_questions");
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ new Guid("3cfe35e8-73d5-4170-9856-f1d078554822"), null, "Student", "STUDENT" },
|
||||||
|
{ new Guid("754c4967-6af2-4a81-b970-1e90a3a269b3"), null, "Teacher", "TEACHER" },
|
||||||
|
{ new Guid("8546457c-185c-4b79-bece-bc21e41d02e7"), null, "Administrator", "ADMINISTRATOR" }
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_assignment_questions_assignment_questions_parent_question_gr~",
|
||||||
|
table: "assignment_questions",
|
||||||
|
column: "parent_question_group_id",
|
||||||
|
principalTable: "assignment_questions",
|
||||||
|
principalColumn: "id");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_submission_details_AspNetUsers_student_id",
|
||||||
|
table: "submission_details",
|
||||||
|
column: "student_id",
|
||||||
|
principalTable: "AspNetUsers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_submissions_AspNetUsers_student_id",
|
||||||
|
table: "submissions",
|
||||||
|
column: "student_id",
|
||||||
|
principalTable: "AspNetUsers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1241
TechHelper.Server/Migrations/20250627101514_upde.Designer.cs
generated
Normal file
1241
TechHelper.Server/Migrations/20250627101514_upde.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
71
TechHelper.Server/Migrations/20250627101514_upde.cs
Normal file
71
TechHelper.Server/Migrations/20250627101514_upde.cs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
|
||||||
|
|
||||||
|
namespace TechHelper.Server.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class upde : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("5f0c1b3c-ad05-4ca9-b9fd-a359cb518236"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("a81f5de2-9691-45fa-8d31-ae4ffeb34453"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("c310acf7-9605-4c55-8b9f-9bf9cd2dadb9"));
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ new Guid("c0f247ab-b12a-432e-8ce7-d0e28811957e"), null, "Student", "STUDENT" },
|
||||||
|
{ new Guid("f282e759-deb5-4366-aaf1-51366131cf75"), null, "Administrator", "ADMINISTRATOR" },
|
||||||
|
{ new Guid("f9eeea07-eeda-4bbe-a2e4-6aef2f3c7c9a"), null, "Teacher", "TEACHER" }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("c0f247ab-b12a-432e-8ce7-d0e28811957e"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("f282e759-deb5-4366-aaf1-51366131cf75"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("f9eeea07-eeda-4bbe-a2e4-6aef2f3c7c9a"));
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ new Guid("5f0c1b3c-ad05-4ca9-b9fd-a359cb518236"), null, "Teacher", "TEACHER" },
|
||||||
|
{ new Guid("a81f5de2-9691-45fa-8d31-ae4ffeb34453"), null, "Administrator", "ADMINISTRATOR" },
|
||||||
|
{ new Guid("c310acf7-9605-4c55-8b9f-9bf9cd2dadb9"), null, "Student", "STUDENT" }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1250
TechHelper.Server/Migrations/20250627105626_updedd.Designer.cs
generated
Normal file
1250
TechHelper.Server/Migrations/20250627105626_updedd.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
102
TechHelper.Server/Migrations/20250627105626_updedd.cs
Normal file
102
TechHelper.Server/Migrations/20250627105626_updedd.cs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
|
||||||
|
|
||||||
|
namespace TechHelper.Server.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class updedd : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("c0f247ab-b12a-432e-8ce7-d0e28811957e"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("f282e759-deb5-4366-aaf1-51366131cf75"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("f9eeea07-eeda-4bbe-a2e4-6aef2f3c7c9a"));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<Guid>(
|
||||||
|
name: "AssignmentId",
|
||||||
|
table: "assignment_questions",
|
||||||
|
type: "char(36)",
|
||||||
|
nullable: true,
|
||||||
|
collation: "ascii_general_ci");
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ new Guid("cf16c215-63f8-4962-8ad0-058274ecf944"), null, "Administrator", "ADMINISTRATOR" },
|
||||||
|
{ new Guid("e3bff43c-36af-497a-971c-ed0a487bdd38"), null, "Student", "STUDENT" },
|
||||||
|
{ new Guid("f05c125e-e70f-40eb-9e19-6e69c3426849"), null, "Teacher", "TEACHER" }
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_assignment_questions_AssignmentId",
|
||||||
|
table: "assignment_questions",
|
||||||
|
column: "AssignmentId");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_assignment_questions_assignments_AssignmentId",
|
||||||
|
table: "assignment_questions",
|
||||||
|
column: "AssignmentId",
|
||||||
|
principalTable: "assignments",
|
||||||
|
principalColumn: "id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_assignment_questions_assignments_AssignmentId",
|
||||||
|
table: "assignment_questions");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_assignment_questions_AssignmentId",
|
||||||
|
table: "assignment_questions");
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("cf16c215-63f8-4962-8ad0-058274ecf944"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("e3bff43c-36af-497a-971c-ed0a487bdd38"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("f05c125e-e70f-40eb-9e19-6e69c3426849"));
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "AssignmentId",
|
||||||
|
table: "assignment_questions");
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ new Guid("c0f247ab-b12a-432e-8ce7-d0e28811957e"), null, "Student", "STUDENT" },
|
||||||
|
{ new Guid("f282e759-deb5-4366-aaf1-51366131cf75"), null, "Administrator", "ADMINISTRATOR" },
|
||||||
|
{ new Guid("f9eeea07-eeda-4bbe-a2e4-6aef2f3c7c9a"), null, "Teacher", "TEACHER" }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -165,6 +165,9 @@ namespace TechHelper.Server.Migrations
|
|||||||
.HasColumnType("char(36)")
|
.HasColumnType("char(36)")
|
||||||
.HasColumnName("id");
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
b.Property<Guid?>("AssignmentId")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
b.Property<DateTime>("CreatedAt")
|
||||||
.HasColumnType("datetime(6)")
|
.HasColumnType("datetime(6)")
|
||||||
.HasColumnName("created_at");
|
.HasColumnName("created_at");
|
||||||
@@ -195,6 +198,11 @@ namespace TechHelper.Server.Migrations
|
|||||||
.HasColumnType("float")
|
.HasColumnType("float")
|
||||||
.HasColumnName("score");
|
.HasColumnName("score");
|
||||||
|
|
||||||
|
b.Property<string>("Sequence")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext")
|
||||||
|
.HasColumnName("sequence");
|
||||||
|
|
||||||
b.Property<byte>("StructType")
|
b.Property<byte>("StructType")
|
||||||
.HasColumnType("tinyint unsigned")
|
.HasColumnType("tinyint unsigned")
|
||||||
.HasColumnName("group_state");
|
.HasColumnName("group_state");
|
||||||
@@ -206,6 +214,8 @@ namespace TechHelper.Server.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AssignmentId");
|
||||||
|
|
||||||
b.HasIndex("ParentAssignmentQuestionId");
|
b.HasIndex("ParentAssignmentQuestionId");
|
||||||
|
|
||||||
b.HasIndex("QuestionContextId");
|
b.HasIndex("QuestionContextId");
|
||||||
@@ -509,7 +519,6 @@ namespace TechHelper.Server.Migrations
|
|||||||
.HasColumnName("deleted");
|
.HasColumnName("deleted");
|
||||||
|
|
||||||
b.Property<string>("OverallFeedback")
|
b.Property<string>("OverallFeedback")
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("longtext")
|
.HasColumnType("longtext")
|
||||||
.HasColumnName("overall_feedback");
|
.HasColumnName("overall_feedback");
|
||||||
|
|
||||||
@@ -576,7 +585,6 @@ namespace TechHelper.Server.Migrations
|
|||||||
.HasColumnName("points_awarded");
|
.HasColumnName("points_awarded");
|
||||||
|
|
||||||
b.Property<string>("StudentAnswer")
|
b.Property<string>("StudentAnswer")
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("longtext")
|
.HasColumnType("longtext")
|
||||||
.HasColumnName("student_answer");
|
.HasColumnName("student_answer");
|
||||||
|
|
||||||
@@ -589,7 +597,6 @@ namespace TechHelper.Server.Migrations
|
|||||||
.HasColumnName("submission_id");
|
.HasColumnName("submission_id");
|
||||||
|
|
||||||
b.Property<string>("TeacherFeedback")
|
b.Property<string>("TeacherFeedback")
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("longtext")
|
.HasColumnType("longtext")
|
||||||
.HasColumnName("teacher_feedback");
|
.HasColumnName("teacher_feedback");
|
||||||
|
|
||||||
@@ -744,19 +751,19 @@ namespace TechHelper.Server.Migrations
|
|||||||
b.HasData(
|
b.HasData(
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("a203eb76-97f0-418f-bc06-9549297d2ac3"),
|
Id = new Guid("e3bff43c-36af-497a-971c-ed0a487bdd38"),
|
||||||
Name = "Student",
|
Name = "Student",
|
||||||
NormalizedName = "STUDENT"
|
NormalizedName = "STUDENT"
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("195b19c5-fd30-455c-9f38-9842b44bf5c3"),
|
Id = new Guid("f05c125e-e70f-40eb-9e19-6e69c3426849"),
|
||||||
Name = "Teacher",
|
Name = "Teacher",
|
||||||
NormalizedName = "TEACHER"
|
NormalizedName = "TEACHER"
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("53cc63db-74bc-47a8-b71a-7e120d4018a9"),
|
Id = new Guid("cf16c215-63f8-4962-8ad0-058274ecf944"),
|
||||||
Name = "Administrator",
|
Name = "Administrator",
|
||||||
NormalizedName = "ADMINISTRATOR"
|
NormalizedName = "ADMINISTRATOR"
|
||||||
});
|
});
|
||||||
@@ -874,7 +881,7 @@ namespace TechHelper.Server.Migrations
|
|||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.HasOne("Entities.Contracts.AssignmentQuestion", "ExamStruct")
|
b.HasOne("Entities.Contracts.AssignmentQuestion", "ExamStruct")
|
||||||
.WithOne("Assignment")
|
.WithOne()
|
||||||
.HasForeignKey("Entities.Contracts.Assignment", "ExamStructId")
|
.HasForeignKey("Entities.Contracts.Assignment", "ExamStructId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
@@ -920,9 +927,14 @@ namespace TechHelper.Server.Migrations
|
|||||||
|
|
||||||
modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b =>
|
modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b =>
|
||||||
{
|
{
|
||||||
|
b.HasOne("Entities.Contracts.Assignment", "Assignment")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AssignmentId");
|
||||||
|
|
||||||
b.HasOne("Entities.Contracts.AssignmentQuestion", "ParentAssignmentQuestion")
|
b.HasOne("Entities.Contracts.AssignmentQuestion", "ParentAssignmentQuestion")
|
||||||
.WithMany("ChildrenAssignmentQuestion")
|
.WithMany("ChildrenAssignmentQuestion")
|
||||||
.HasForeignKey("ParentAssignmentQuestionId");
|
.HasForeignKey("ParentAssignmentQuestionId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
b.HasOne("Entities.Contracts.QuestionContext", "QuestionContext")
|
b.HasOne("Entities.Contracts.QuestionContext", "QuestionContext")
|
||||||
.WithMany("Questions")
|
.WithMany("Questions")
|
||||||
@@ -934,6 +946,8 @@ namespace TechHelper.Server.Migrations
|
|||||||
.HasForeignKey("QuestionId")
|
.HasForeignKey("QuestionId")
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.Navigation("Assignment");
|
||||||
|
|
||||||
b.Navigation("ParentAssignmentQuestion");
|
b.Navigation("ParentAssignmentQuestion");
|
||||||
|
|
||||||
b.Navigation("Question");
|
b.Navigation("Question");
|
||||||
@@ -1064,7 +1078,7 @@ namespace TechHelper.Server.Migrations
|
|||||||
b.HasOne("Entities.Contracts.User", "Student")
|
b.HasOne("Entities.Contracts.User", "Student")
|
||||||
.WithMany("SubmissionsAsStudent")
|
.WithMany("SubmissionsAsStudent")
|
||||||
.HasForeignKey("StudentId")
|
.HasForeignKey("StudentId")
|
||||||
.OnDelete(DeleteBehavior.Restrict)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.Navigation("Assignment");
|
b.Navigation("Assignment");
|
||||||
@@ -1085,7 +1099,7 @@ namespace TechHelper.Server.Migrations
|
|||||||
b.HasOne("Entities.Contracts.User", "Student")
|
b.HasOne("Entities.Contracts.User", "Student")
|
||||||
.WithMany("SubmissionDetails")
|
.WithMany("SubmissionDetails")
|
||||||
.HasForeignKey("StudentId")
|
.HasForeignKey("StudentId")
|
||||||
.OnDelete(DeleteBehavior.Restrict)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.HasOne("Entities.Contracts.Submission", "Submission")
|
b.HasOne("Entities.Contracts.Submission", "Submission")
|
||||||
@@ -1163,8 +1177,6 @@ namespace TechHelper.Server.Migrations
|
|||||||
|
|
||||||
modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b =>
|
modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("Assignment");
|
|
||||||
|
|
||||||
b.Navigation("ChildrenAssignmentQuestion");
|
b.Navigation("ChildrenAssignmentQuestion");
|
||||||
|
|
||||||
b.Navigation("SubmissionDetails");
|
b.Navigation("SubmissionDetails");
|
||||||
|
@@ -12,6 +12,7 @@ using TechHelper.Features;
|
|||||||
using TechHelper.Services;
|
using TechHelper.Services;
|
||||||
using TechHelper.Server.Services;
|
using TechHelper.Server.Services;
|
||||||
using TechHelper.Server.Repositories;
|
using TechHelper.Server.Repositories;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
@@ -90,7 +91,35 @@ builder.Services.AddScoped<IExamRepository, ExamRepository>();
|
|||||||
|
|
||||||
|
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddSwaggerGen();
|
builder.Services.AddSwaggerGen(c =>
|
||||||
|
{
|
||||||
|
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Your API Name", Version = "v1" });
|
||||||
|
|
||||||
|
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Name = "Authorization",
|
||||||
|
Type = SecuritySchemeType.Http,
|
||||||
|
Scheme = "bearer",
|
||||||
|
BearerFormat = "JWT",
|
||||||
|
In = ParameterLocation.Header,
|
||||||
|
Description = "JWT Authorization header using the Bearer scheme. \r\n\r\n Enter 'Bearer' [space] and then your token in the text input below.\r\n\r\nExample: \"Bearer 12345abcdef\"",
|
||||||
|
});
|
||||||
|
|
||||||
|
c.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||||
|
{
|
||||||
|
{
|
||||||
|
new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Reference = new OpenApiReference
|
||||||
|
{
|
||||||
|
Type = ReferenceType.SecurityScheme,
|
||||||
|
Id = "Bearer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new string[] {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
builder.Services.AddCors(options =>
|
builder.Services.AddCors(options =>
|
||||||
|
@@ -17,7 +17,7 @@ namespace TechHelper.Server.Repositories
|
|||||||
{
|
{
|
||||||
_unitOfWork = unitOfWork;
|
_unitOfWork = unitOfWork;
|
||||||
_assignmentRepo = _unitOfWork.GetRepository<Assignment>();
|
_assignmentRepo = _unitOfWork.GetRepository<Assignment>();
|
||||||
_assignQuestionRepo = _unitOfWork.GetRepository<AssignmentQuestion>();
|
_assignQuestionRepo = _unitOfWork.GetRepository<AssignmentQuestion>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Assignment?> GetFullExamByIdAsync(Guid assignmentId)
|
public async Task<Assignment?> GetFullExamByIdAsync(Guid assignmentId)
|
||||||
@@ -29,18 +29,18 @@ namespace TechHelper.Server.Repositories
|
|||||||
i => i.Include(a => a.ExamStruct)
|
i => i.Include(a => a.ExamStruct)
|
||||||
);
|
);
|
||||||
|
|
||||||
result.ExamStruct = await GetNeed(result.ExamStructId)?? null;
|
result.ExamStruct = await GetNeed(result.ExamStructId) ?? null;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<AssignmentQuestion?> GetNeed(Guid id)
|
public async Task<AssignmentQuestion?> GetNeed(Guid id)
|
||||||
{
|
{
|
||||||
var result = await _assignQuestionRepo.GetFirstOrDefaultAsync(
|
var result = await _assignQuestionRepo.GetFirstOrDefaultAsync(
|
||||||
predicate: aq => aq.Id == id,
|
predicate: aq => aq.Id == id,
|
||||||
include: i => i
|
include: i => i
|
||||||
.Include(aq => aq.ChildrenAssignmentQuestion)
|
.Include(aq => aq.ChildrenAssignmentQuestion)
|
||||||
.Include(aq => aq.Question)
|
.Include(aq => aq.Question)
|
||||||
.ThenInclude(q => q.Lesson)
|
.ThenInclude(q => q.Lesson)
|
||||||
.Include(aq => aq.Question)
|
.Include(aq => aq.Question)
|
||||||
@@ -55,13 +55,13 @@ namespace TechHelper.Server.Repositories
|
|||||||
var loadedChildren = new List<AssignmentQuestion>();
|
var loadedChildren = new List<AssignmentQuestion>();
|
||||||
foreach (var child in result.ChildrenAssignmentQuestion)
|
foreach (var child in result.ChildrenAssignmentQuestion)
|
||||||
{
|
{
|
||||||
var loadedChild = await GetNeed(child.Id);
|
var loadedChild = await GetNeed(child.Id);
|
||||||
if (loadedChild != null)
|
if (loadedChild != null)
|
||||||
{
|
{
|
||||||
loadedChildren.Add(loadedChild);
|
loadedChildren.Add(loadedChild);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.ChildrenAssignmentQuestion = loadedChildren;
|
result.ChildrenAssignmentQuestion = loadedChildren;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -90,5 +90,18 @@ namespace TechHelper.Server.Repositories
|
|||||||
public async Task AddAsync(AssignmentClass assignment)
|
public async Task AddAsync(AssignmentClass assignment)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task AddAsync(Submission submission)
|
||||||
|
{
|
||||||
|
await _unitOfWork.GetRepository<Submission>().InsertAsync(submission);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Assignment>> GetAllSubmissionPreviewsByUserAsync(Guid id)
|
||||||
|
{
|
||||||
|
var submissions = await _unitOfWork.GetRepository<Submission>().GetAllAsync(predicate: s => s.StudentId == id, include: i => i.Include(s => s.Assignment));
|
||||||
|
if (submissions == null || !submissions.Any())
|
||||||
|
return Enumerable.Empty<Assignment>();
|
||||||
|
return submissions.ToList().Select(s => s.Assignment).Where(a => a != null).Distinct().ToList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using Entities.Contracts;
|
using Entities.Contracts;
|
||||||
|
using Entities.DTO;
|
||||||
|
|
||||||
namespace TechHelper.Server.Repositories
|
namespace TechHelper.Server.Repositories
|
||||||
{
|
{
|
||||||
@@ -23,6 +24,7 @@ namespace TechHelper.Server.Repositories
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="assignment">要添加的试卷实体。</param>
|
/// <param name="assignment">要添加的试卷实体。</param>
|
||||||
Task AddAsync(Assignment assignment);
|
Task AddAsync(Assignment assignment);
|
||||||
|
Task AddAsync(Submission submission);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -32,6 +34,6 @@ namespace TechHelper.Server.Repositories
|
|||||||
Task AddAsync(Question assignment);
|
Task AddAsync(Question assignment);
|
||||||
|
|
||||||
Task AddAsync(AssignmentClass assignment);
|
Task AddAsync(AssignmentClass assignment);
|
||||||
|
Task<IEnumerable<Assignment>> GetAllSubmissionPreviewsByUserAsync(Guid id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -67,15 +67,13 @@ namespace TechHelper.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 实现 IBaseService<ClassDto, int>.GetAllAsync
|
|
||||||
public async Task<ApiResponse> GetAllAsync(QueryParameter query)
|
public async Task<ApiResponse> GetAllAsync(QueryParameter query)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var repository = _work.GetRepository<Class>();
|
var repository = _work.GetRepository<Class>();
|
||||||
|
|
||||||
// 构建查询条件 (可根据 QueryParameter.Search 进行筛选)
|
Func<IQueryable<Class>, IOrderedQueryable<Class>> orderBy = null;
|
||||||
Func<IQueryable<Class>, IOrderedQueryable<Class>> orderBy = null; // 默认不排序
|
|
||||||
if (query.Search != null && !string.IsNullOrWhiteSpace(query.Search))
|
if (query.Search != null && !string.IsNullOrWhiteSpace(query.Search))
|
||||||
{
|
{
|
||||||
// 在 Name 字段中进行模糊搜索
|
// 在 Name 字段中进行模糊搜索
|
||||||
@@ -127,9 +125,22 @@ namespace TechHelper.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<ApiResponse> GetClassStudents(ClassDto classDto)
|
public async Task<ApiResponse> GetClassStudents(ClassDto classDto)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
try
|
||||||
|
{
|
||||||
|
var result = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(predicate:
|
||||||
|
c => c.Grade == classDto.Grade && c.Number == classDto.Class,
|
||||||
|
include: i => i
|
||||||
|
.Include(c => c.ClassStudents)
|
||||||
|
.ThenInclude(cs => cs.Student));
|
||||||
|
|
||||||
|
return ApiResponse.Success(result: result.ClassStudents);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return ApiResponse.Error($"获取学生列表错误, {ex.Message}, {ex.InnerException}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ApiResponse> GetUserClass(Guid id)
|
public async Task<ApiResponse> GetUserClass(Guid id)
|
||||||
@@ -185,9 +196,6 @@ namespace TechHelper.Services
|
|||||||
var existingClass = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
|
var existingClass = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
|
||||||
predicate: (c => c.Number == user.ClassId && c.Grade == user.GradeId));
|
predicate: (c => c.Number == user.ClassId && c.Grade == user.GradeId));
|
||||||
|
|
||||||
// finduser and usrinfo are redundant if they are for the same user.
|
|
||||||
// Let's just use usrinfo
|
|
||||||
// var finduser = await _userManager.FindByEmailAsync(user.User);
|
|
||||||
|
|
||||||
if (existingClass == null || usrinfo == null) // Simplified check
|
if (existingClass == null || usrinfo == null) // Simplified check
|
||||||
{
|
{
|
||||||
|
@@ -57,7 +57,7 @@ namespace TechHelper.Server.Services
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return ApiResponse.Error(ex.Message);
|
return ApiResponse.Error(ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ namespace TechHelper.Server.Services
|
|||||||
public async Task<ApiResponse> GetAllExamPreviewsAsync(Guid userId)
|
public async Task<ApiResponse> GetAllExamPreviewsAsync(Guid userId)
|
||||||
{
|
{
|
||||||
var assignments = await _examRepository.GetExamPreviewsByUserAsync(userId);
|
var assignments = await _examRepository.GetExamPreviewsByUserAsync(userId);
|
||||||
var result = _mapper.Map<List<AssignmentDto>>(assignments);
|
var result = _mapper.Map<List<AssignmentDto>>(assignments);
|
||||||
return ApiResponse.Success(result: result);
|
return ApiResponse.Success(result: result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,11 +109,72 @@ namespace TechHelper.Server.Services
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<ApiResponse> DeleteAsync(Guid id)
|
public async Task<ApiResponse> DeleteAsync(Guid id)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var assignment = await _unitOfWork.GetRepository<Assignment>().GetFirstOrDefaultAsync(predicate: a => a.Id == id);
|
||||||
|
|
||||||
|
if (assignment == null) return ApiResponse.Error("找不到该试卷");
|
||||||
|
_unitOfWork.GetRepository<Assignment>().Delete(id);
|
||||||
|
_unitOfWork.GetRepository<AssignmentQuestion>().Delete(assignment.ExamStructId);
|
||||||
|
|
||||||
|
|
||||||
|
if (await _unitOfWork.SaveChangesAsync() > 0)
|
||||||
|
{
|
||||||
|
return ApiResponse.Success();
|
||||||
|
}
|
||||||
|
return ApiResponse.Error("删除失败");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return ApiResponse.Error("内部问题");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ApiResponse> SubmissionAssignment(SubmissionDto submissionDto)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var submission = _mapper.Map<Submission>(submissionDto);
|
||||||
|
|
||||||
|
await _examRepository.AddAsync(submission);
|
||||||
|
|
||||||
|
if (await _unitOfWork.SaveChangesAsync() > 0)
|
||||||
|
{
|
||||||
|
return ApiResponse.Success("保存成功");
|
||||||
|
}
|
||||||
|
return ApiResponse.Error("保存失败");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return ApiResponse.Error($"出现了错误,{ex.Message} innerEx:{ex.InnerException}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ApiResponse> AssignmentToAllStudentsAsync(Guid id)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task<ApiResponse> AssignmentToStudentsAsync(Guid assignementId, Guid studentId)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ApiResponse> GetAllSubmissionAsync(Guid id)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await _examRepository.GetAllSubmissionPreviewsByUserAsync(id);
|
||||||
|
var allExam = _mapper.Map<List<AssignmentDto>>(result);
|
||||||
|
return ApiResponse.Success(result: allExam);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return ApiResponse.Error($"Submission 内部错误, {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -2,10 +2,10 @@
|
|||||||
{
|
{
|
||||||
public interface IBaseService<T, TId>
|
public interface IBaseService<T, TId>
|
||||||
{
|
{
|
||||||
Task<TechHelper.Services.ApiResponse> GetAllAsync(QueryParameter query);
|
Task<ApiResponse> GetAllAsync(QueryParameter query);
|
||||||
Task<TechHelper.Services.ApiResponse> GetAsync(TId id);
|
Task<ApiResponse> GetAsync(TId id);
|
||||||
Task<TechHelper.Services.ApiResponse> AddAsync(T model);
|
Task<ApiResponse> AddAsync(T model);
|
||||||
Task<TechHelper.Services.ApiResponse> UpdateAsync(T model);
|
Task<ApiResponse> UpdateAsync(T model);
|
||||||
Task<TechHelper.Services.ApiResponse> DeleteAsync(TId id);
|
Task<ApiResponse> DeleteAsync(TId id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,5 +22,17 @@ namespace TechHelper.Server.Services
|
|||||||
/// <returns>创建成功的试卷ID</returns>
|
/// <returns>创建成功的试卷ID</returns>
|
||||||
Task<ApiResponse> CreateExamAsync(AssignmentDto examDto);
|
Task<ApiResponse> CreateExamAsync(AssignmentDto examDto);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Task<ApiResponse> SubmissionAssignment(SubmissionDto submissionDto);
|
||||||
|
|
||||||
|
|
||||||
|
Task<ApiResponse> AssignmentToAllStudentsAsync(Guid id);
|
||||||
|
|
||||||
|
Task<ApiResponse> AssignmentToStudentsAsync(Guid assignementId, Guid studentId);
|
||||||
|
|
||||||
|
|
||||||
|
Task<ApiResponse> GetAllSubmissionAsync(Guid id);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
TechHelper.Server/Services/ISubmissionServices.cs
Normal file
16
TechHelper.Server/Services/ISubmissionServices.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using Entities.Contracts;
|
||||||
|
using TechHelper.Services;
|
||||||
|
|
||||||
|
namespace TechHelper.Server.Services
|
||||||
|
{
|
||||||
|
public interface ISubmissionServices : IBaseService<Submission, Guid>
|
||||||
|
{
|
||||||
|
Task<ApiResponse> GetAssignmentErrorQuestionsAsync(Guid assignmentId, Guid userId);
|
||||||
|
Task<ApiResponse> GetAllErrorQuestionsAsync(Guid userId);
|
||||||
|
Task<ApiResponse> GetAssignmentErrorQuestionTypeDisAsync(Guid assignmentId, Guid userId);
|
||||||
|
Task<ApiResponse> GetAllErrorQuestionTypeDisAsync(Guid assignmentId, Guid userId);
|
||||||
|
|
||||||
|
Task<ApiResponse> GetAssignmentAllStudentsError(Guid assignmentId, Guid teacherId);
|
||||||
|
Task<ApiResponse> GetQuestionErrorStudents(Guid assignmentId);
|
||||||
|
}
|
||||||
|
}
|
10
TechHelper.Server/Services/IUserSerivces.cs
Normal file
10
TechHelper.Server/Services/IUserSerivces.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using Entities.Contracts;
|
||||||
|
using TechHelper.Services;
|
||||||
|
|
||||||
|
namespace TechHelper.Server.Services
|
||||||
|
{
|
||||||
|
public interface IUserSerivces : IBaseService<User, Guid>
|
||||||
|
{
|
||||||
|
Task<ApiResponse> GetStudentDetailInfo(Guid userId);
|
||||||
|
}
|
||||||
|
}
|
91
TechHelper.Server/Services/SubmissionServices.cs
Normal file
91
TechHelper.Server/Services/SubmissionServices.cs
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
using AutoMapper;
|
||||||
|
using Entities.Contracts;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SharedDATA.Api;
|
||||||
|
using TechHelper.Services;
|
||||||
|
|
||||||
|
namespace TechHelper.Server.Services
|
||||||
|
{
|
||||||
|
public class SubmissionServices : ISubmissionServices
|
||||||
|
{
|
||||||
|
private readonly IUnitOfWork _unitOfWork;
|
||||||
|
private readonly IMapper _mapper;
|
||||||
|
private readonly IRepository<Submission> _submissionRepository;
|
||||||
|
private readonly IRepository<SubmissionDetail> _submissionDetailRepository;
|
||||||
|
|
||||||
|
public SubmissionServices(IMapper mapper, IUnitOfWork unitOfWork)
|
||||||
|
{
|
||||||
|
_mapper = mapper;
|
||||||
|
_unitOfWork = unitOfWork;
|
||||||
|
_submissionRepository = _unitOfWork.GetRepository<Submission>();
|
||||||
|
_submissionDetailRepository = _unitOfWork.GetRepository<SubmissionDetail>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ApiResponse> AddAsync(Submission model)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ApiResponse> DeleteAsync(Guid id)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ApiResponse> GetAllAsync(QueryParameter query)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
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.AssignmentQuestion)
|
||||||
|
.ThenInclude(aq => aq.Question));
|
||||||
|
var errorQuestion = errorSDs.Items.Select(sd => sd.AssignmentQuestion).ToList();
|
||||||
|
return ApiResponse.Success();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return ApiResponse.Error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ApiResponse> GetAllErrorQuestionTypeDisAsync(Guid assignmentId, Guid userId)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ApiResponse> GetAssignmentAllStudentsError(Guid assignmentId, Guid teacherId)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ApiResponse> GetAssignmentErrorQuestionsAsync(Guid assignmentId, Guid userId)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ApiResponse> GetAssignmentErrorQuestionTypeDisAsync(Guid assignmentId, Guid userId)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ApiResponse> GetAsync(Guid id)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ApiResponse> GetQuestionErrorStudents(Guid assignmentId)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ApiResponse> UpdateAsync(Submission model)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
TechHelper.Server/Services/UserServices.cs
Normal file
38
TechHelper.Server/Services/UserServices.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using Entities.Contracts;
|
||||||
|
using TechHelper.Services;
|
||||||
|
|
||||||
|
namespace TechHelper.Server.Services
|
||||||
|
{
|
||||||
|
public class UserServices : IUserSerivces
|
||||||
|
{
|
||||||
|
public Task<ApiResponse> AddAsync(User model)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ApiResponse> DeleteAsync(Guid id)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ApiResponse> GetAllAsync(QueryParameter query)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ApiResponse> GetAsync(Guid id)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ApiResponse> GetStudentDetailInfo(Guid userId)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ApiResponse> UpdateAsync(User model)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user