重构项目结构,移除Assignment相关功能,优化Submission模块
Some checks failed
TechAct / explore-gitea-actions (push) Failing after 12s

This commit is contained in:
SpecialX
2025-10-09 18:57:28 +08:00
parent 403b34a098
commit ac900159ba
289 changed files with 11948 additions and 20150 deletions

View File

@@ -1,5 +1,4 @@
using TechHelper.Context.Configuration;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Entities.Contracts;
@@ -11,31 +10,29 @@ namespace TechHelper.Context
public ApplicationContext(DbContextOptions options)
: base(options) { }
public DbSet<AssignmentClass> AssignmentClasses { get; set; }
public DbSet<Assignment> Assignments { get; set; }
public DbSet<AssignmentQuestion> AssignmentQuestions { get; set; }
public DbSet<School> Schools { get; set; }
public DbSet<Grade> Grades { get; set; }
public DbSet<Class> Classes { get; set; }
public DbSet<ClassTeacher> ClassStudents { get; set; }
public DbSet<ClassTeacher> ClassTeachers { get; set; }
public DbSet<Exam> Exams { get; set; }
public DbSet<ExamQuestion> ExamQuestions { get; set; }
public DbSet<ExamAttachment> ExamAttachments{ get; set; }
public DbSet<ExamType> ExamTypes { get; set; }
public DbSet<Question> Questions { get; set; }
public DbSet<Submission> Submissions { get; set; }
public DbSet<SubmissionDetail> SubmissionDetails { get; set; }
public DbSet<QuestionContext> QuestionContexts { get; set; }
public DbSet<Global> Globals { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ApplyConfiguration(new RoleConfiguration());
builder.ApplyConfiguration(new AssignmentConfiguration());
builder.ApplyConfiguration(new AssignmentClassConfiguration());
builder.ApplyConfiguration(new AssignmentQuestionConfiguration());
builder.ApplyConfiguration(new ClassConfiguration());
builder.ApplyConfiguration(new ClassStudentConfiguration());
builder.ApplyConfiguration(new ClassTeacherConfiguration());
builder.ApplyConfiguration(new QuestionConfiguration());
builder.ApplyConfiguration(new SubmissionConfiguration());
builder.ApplyConfiguration(new SubmissionDetailConfiguration());
}
//protected override void OnModelCreating(ModelBuilder builder)
//{
// base.OnModelCreating(builder);
// builder.ApplyConfiguration(new RoleConfiguration());
// builder.ApplyConfiguration(new AssignmentConfiguration());
// builder.ApplyConfiguration(new AssignmentClassConfiguration());
// builder.ApplyConfiguration(new AssignmentQuestionConfiguration());
// builder.ApplyConfiguration(new ClassConfiguration());
// builder.ApplyConfiguration(new QuestionConfiguration());
// builder.ApplyConfiguration(new SubmissionConfiguration());
// builder.ApplyConfiguration(new SubmissionDetailConfiguration());
//}
}
}

View File

@@ -1,11 +1,7 @@
using AutoMapper;
using AutoMapper.Internal.Mappers;
using Entities.Contracts;
using Entities.DTO;
using Newtonsoft.Json;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using Entities.DTO.Class;
namespace TechHelper.Context
{
@@ -28,53 +24,91 @@ namespace TechHelper.Context
{
CreateMap<UserForRegistrationDto, User>()
.ForMember(dest => dest.Id, opt => opt.Ignore())
.ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.Name))
.ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.DisplayName))
.ForMember(dest => dest.Email, opt => opt.MapFrom(src => src.Email))
.ForMember(dest => dest.PhoneNumber, opt => opt.MapFrom(src => src.PhoneNumber))
.ForMember(dest => dest.Address, opt => opt.MapFrom(src => src.HomeAddress))
.ForMember(dest => dest.HomeAddress, opt => opt.MapFrom(src => src.HomeAddress))
.ForMember(dest => dest.PasswordHash, opt => opt.Ignore())
.ForMember(dest => dest.EmailConfirmed, opt => opt.Ignore());
CreateMap<ClassDto, Class>()
.ForMember(d => d.Number, o => o.MapFrom(src => src.Class))
.ReverseMap();
// Subject
CreateMap<Subject, SubjectDto>().ReverseMap();
CreateMap<Subject, SubjectResponseDto>().ReverseMap();
CreateMap<Subject, TypeCommonDto>().ReverseMap();
// ExamType
CreateMap<ExamType, ExamTypeDto>().ReverseMap();
CreateMap<ExamType, TypeCommonDto>().ReverseMap();
// QuestionType
CreateMap<QuestionType, QuestionTypeDto >().ReverseMap();
CreateMap<QuestionType, TypeCommonDto>().ReverseMap();
// Exam
CreateMap<ExamDto, Exam>().ReverseMap();
CreateMap<Exam, ExamListDto>().ReverseMap();
// Assignment
CreateMap<AssignmentDto, Assignment>().ReverseMap();
CreateMap<AssignmentQuestionDto, AssignmentQuestion>().ReverseMap();
CreateMap<ExamQuestionDto, ExamQuestion>().ReverseMap();
CreateMap<QuestionDto, Question>().ReverseMap();
CreateMap<QuestionContext, QuestionContextDto>().ReverseMap();
// Submission
CreateMap<SubmissionDto, Submission>().ReverseMap();
CreateMap<SubmissionDetailDto, SubmissionDetail>().ReverseMap();
CreateMap<SubmissionTeacherUpdateDto, Submission>().ReverseMap();
// Student Submission Detail
CreateMap<Submission, StudentSubmissionDetailDto>()
.ForMember(dest => dest.AssignmentId, opt => opt.MapFrom(src => src.AssignmentId))
.ForMember(dest => dest.AssignmentId, opt => opt.MapFrom(src => src.ExamId))
.ForMember(dest => dest.StudentId, opt => opt.MapFrom(src => src.StudentId))
.ForMember(dest => dest.SubmissionTime, opt => opt.MapFrom(src => src.SubmissionTime))
.ForMember(dest => dest.OverallGrade, opt => opt.MapFrom(src => src.OverallGrade))
.ForMember(dest => dest.OverallFeedback, opt => opt.MapFrom(src => src.OverallFeedback))
.ForMember(dest => dest.Status, opt => opt.MapFrom(src => src.Status));
CreateMap<Assignment, AssignmentDto>().ReverseMap();
CreateMap<Submission, SubmissionListDto>().ReverseMap();
CreateMap<SubmissionDetail, SubmissionDetailTeacherUpdateDto>().ReverseMap();
CreateMap<SubjectTypeMetadataDto, Global>()
.ForMember(dest => dest.Info, opt => opt.MapFrom(src => JsonConvert.SerializeObject(src.Data)));
CreateMap<Global, SubjectTypeMetadataDto>()
.ForMember(dest => dest.Data, opt => opt.MapFrom(src => JsonConvert.DeserializeObject<Dictionary<string, (string Color, string DisplayName)>>(src.Info)));
// School
CreateMap<SchoolDto, School>().ReverseMap();
CreateMap<SchoolResponseDto, School>().ReverseMap();
// Grade
CreateMap<GradeDto, Grade>().ReverseMap();
CreateMap<CreateGradeDto, Grade>().ReverseMap();
// Class
CreateMap<ClassDto, Class>().ReverseMap();
CreateMap<ClassCreateDto, Class>().ReverseMap();
// User
CreateMap<User, UserDto>().ReverseMap();
CreateMap<User, UserListDto>().ReverseMap();
// KeyPoint
CreateMap<KeyPoint, KeyPointDto>().ReverseMap();
CreateMap<KeyPoint, CreateKeyPointDto>().ReverseMap();
CreateMap<KeyPoint, UpdateKeyPointDto>().ReverseMap();
CreateMap<KeyPoint, KeyPointResponseDto>().ReverseMap();
// Lesson
CreateMap<Lesson, LessonDto>().ReverseMap();
CreateMap<Lesson, CreateLessonDto>().ReverseMap();
CreateMap<Lesson, UpdateLessonDto>().ReverseMap();
CreateMap<Lesson, LessonResponseDto>().ReverseMap();
// Textbook
CreateMap<Textbook, TextbookDto>().ReverseMap();
CreateMap<Textbook, CreateTextbookDto>().ReverseMap();
CreateMap<Textbook, UpdateTextbookDto>().ReverseMap();
CreateMap<Textbook, TextbookResponseDto>()
.ForMember(dest => dest.LessonCount, opt => opt.MapFrom(src => src.Lessons.Count))
.ForMember(dest => dest.LessonTitles, opt => opt.MapFrom(src => src.Lessons.Select(l => l.Title).ToList()));
}
}

View File

@@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore;
namespace TechHelper.Context.Configuration
{
public class AssignmentAttachmentConfiguration : IEntityTypeConfiguration<AssignmentAttachment>
public class AssignmentAttachmentConfiguration : IEntityTypeConfiguration<ExamAttachment>
{
public void Configure(EntityTypeBuilder<AssignmentAttachment> builder)
public void Configure(EntityTypeBuilder<ExamAttachment> builder)
{
builder.ToTable("assignment_attachments");
@@ -38,8 +38,8 @@ namespace TechHelper.Context.Configuration
.HasDefaultValue(false);
// Configure the relationship explicitly
builder.HasOne(aa => aa.Assignment) // An AssignmentAttachment has one Assignment
.WithMany(a => a.AssignmentAttachments) // An Assignment has many AssignmentAttachments (assuming 'Attachments' collection in Assignment)
builder.HasOne(aa => aa.Exam) // An AssignmentAttachment has one Assignment
.WithMany(a => a.ExamAttachments) // An Assignment has many AssignmentAttachments (assuming 'Attachments' collection in Assignment)
.HasForeignKey(aa => aa.AssignmentId) // The foreign key is AssignmentAttachment.AssignmentId
.IsRequired() // It's a required relationship based on your [Required] attribute
.OnDelete(DeleteBehavior.Cascade); // If an Assignment is deleted, its attachments should also be deleted

View File

@@ -4,18 +4,18 @@ using Microsoft.EntityFrameworkCore;
namespace TechHelper.Context.Configuration
{
public class AssignmentClassConfiguration : IEntityTypeConfiguration<AssignmentClass>
public class AssignmentClassConfiguration : IEntityTypeConfiguration<ExamClass>
{
public void Configure(EntityTypeBuilder<AssignmentClass> builder)
public void Configure(EntityTypeBuilder<ExamClass> builder)
{
// 设置表名为 "assignment_class"
builder.ToTable("assignment_class");
// 设置复合主键
builder.HasKey(ac => new { ac.AssignmentId, ac.ClassId });
builder.HasKey(ac => new { ac.ExamId, ac.ClassId });
// 配置 AssignmentId 列名
builder.Property(ac => ac.AssignmentId)
builder.Property(ac => ac.ExamId)
.HasColumnName("assignment_id");
// 配置 ClassId 列名
@@ -34,15 +34,15 @@ namespace TechHelper.Context.Configuration
// 配置到 Assignment 的关系 (多对一)
// 假设 Assignment 类中有一个名为 AssignmentClasses 的集合属性
builder.HasOne(ac => ac.Assignment) // AssignmentClass 有一个 Assignment
builder.HasOne(ac => ac.Exam) // AssignmentClass 有一个 Assignment
.WithMany(a => a.AssignmentClasses) // Assignment 有多个 AssignmentClass 记录
.HasForeignKey(ac => ac.AssignmentId) // 通过 AssignmentId 建立外键
.HasForeignKey(ac => ac.ExamId) // 通过 AssignmentId 建立外键
.OnDelete(DeleteBehavior.Cascade); // 当 Assignment 被删除时,相关的 AssignmentClass 记录也级联删除
// 配置到 Class 的关系 (多对一)
// 假设 Class 类中有一个名为 AssignmentClasses 的集合属性
builder.HasOne(ac => ac.Class) // AssignmentClass 有一个 Class
.WithMany(c => c.AssignmentClasses) // Class 有多个 AssignmentClass 记录
.WithMany(c => c.ExamClasses) // Class 有多个 AssignmentClass 记录
.HasForeignKey(ac => ac.ClassId) // 通过 ClassId 建立外键
.OnDelete(DeleteBehavior.Cascade); // 当 Class 被删除时,相关的 AssignmentClass 记录也级联删除
}

View File

@@ -5,9 +5,9 @@ using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace TechHelper.Context.Configuration
{
public class AssignmentConfiguration : IEntityTypeConfiguration<Assignment>
public class AssignmentConfiguration : IEntityTypeConfiguration<Exam>
{
public void Configure(EntityTypeBuilder<Assignment> builder)
public void Configure(EntityTypeBuilder<Exam> builder)
{
builder.ToTable("assignments");
@@ -61,7 +61,7 @@ namespace TechHelper.Context.Configuration
builder.HasOne(a=>a.ExamStruct)
.WithOne()
.HasForeignKey<Assignment>(a=>a.ExamStructId)
.HasForeignKey<Exam>(a=>a.ExamStructId)
.OnDelete(DeleteBehavior.Cascade);
}

View File

@@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore;
namespace TechHelper.Context.Configuration
{
public class AssignmentQuestionConfiguration : IEntityTypeConfiguration<AssignmentQuestion>
public class AssignmentQuestionConfiguration : IEntityTypeConfiguration<ExamQuestion>
{
public void Configure(EntityTypeBuilder<AssignmentQuestion> builder)
public void Configure(EntityTypeBuilder<ExamQuestion> builder)
{
// 1. 设置表名
builder.ToTable("assignment_questions");
@@ -44,13 +44,13 @@ namespace TechHelper.Context.Configuration
builder.HasOne(aq => aq.Question)
.WithMany(q => q.AssignmentQuestions)
.WithMany(q => q.ExamQuestions)
.HasForeignKey(aq => aq.QuestionId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasOne(aq => aq.ParentAssignmentQuestion)
builder.HasOne(aq => aq.ParentExamQuestion)
.WithMany(aq => aq.ChildrenAssignmentQuestion)
.HasForeignKey(aq => aq.ParentAssignmentQuestionId)
.HasForeignKey(aq => aq.ParentExamQuestionId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasOne(aq => aq.QuestionContext)

View File

@@ -86,7 +86,7 @@ namespace TechHelper.Context.Configuration
// 11. 与 AssignmentClass 的关系 (多对多中间表或一对多)
// 一对多:一个 Class 有多个 AssignmentClass。一个 AssignmentClass 属于一个 Class。
// 假设 AssignmentClass 有 'ClassId' 外键和 'Class' 导航属性。
builder.HasMany(c => c.AssignmentClasses) // Class 中的集合导航属性
builder.HasMany(c => c.ExamClasses) // Class 中的集合导航属性
.WithOne(ac => ac.Class) // 假设 AssignmentClass 中有 'public Class Class { get; set; }'
.HasForeignKey(ac => ac.ClassId) // 假设 AssignmentClass 中有 'public Guid ClassId { get; set; }'
.OnDelete(DeleteBehavior.Cascade); // 常见:如果一个班级被删除,其作业关联也应被删除。

View File

@@ -1,64 +0,0 @@
using Entities.Contracts;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore;
namespace TechHelper.Context.Configuration
{
public class ClassStudentConfiguration : IEntityTypeConfiguration<ClassStudent>
{
public void Configure(EntityTypeBuilder<ClassStudent> builder)
{
// 1. 设置表名
// 将此实体映射到数据库中名为 "class_student" 的表。
builder.ToTable("class_student");
// 2. 设置复合主键
// ClassId 和 StudentId 的组合作为主键,确保一个班级中一个学生只有一条入学记录。
builder.HasKey(cs => new { cs.ClassId, cs.StudentId });
// 3. 配置列名和属性特性
// 配置 ClassId 属性对应的数据库列名为 "class_id"。
builder.Property(cs => cs.ClassId)
.HasColumnName("class_id");
// 配置 StudentId 属性对应的数据库列名为 "student_id"。
builder.Property(cs => cs.StudentId)
.HasColumnName("student_id");
// 配置 EnrollmentDate 属性对应的数据库列名为 "enrollment_date",并设置为必需字段。
builder.Property(cs => cs.EnrollmentDate)
.HasColumnName("enrollment_date")
.IsRequired();
// 配置 IsDeleted 属性对应的数据库列名为 "deleted",并设置默认值为 false。
builder.Property(cs => cs.IsDeleted)
.HasColumnName("deleted")
.HasDefaultValue(false); // 常用作软删除标记
// 4. 配置导航属性和外键关系
// ---
// 配置 ClassStudent 到 Class 的关系 (多对一)
// 一个 ClassStudent 联结记录属于一个 Class。
//
// 假设 `Class` 实体中有一个名为 `ClassStudents` 的 `ICollection<ClassStudent>` 集合属性。
builder.HasOne(cs => cs.Class) // 当前 ClassStudent 链接到一个 Class
.WithMany(c => c.ClassStudents) // 那个 Class 可以有多个 ClassStudent 记录
.HasForeignKey(cs => cs.ClassId) // 外键是 ClassStudent.ClassId
.OnDelete(DeleteBehavior.Cascade); // 当 Class 被删除时,相关的 ClassStudent 记录也级联删除。
// ---
// 配置 ClassStudent 到 User (Student) 的关系 (多对一)
// 一个 ClassStudent 联结记录属于一个 User (作为 Student)。
//
// 假设 `User` 实体中有一个名为 `EnrolledClassesLink` 的 `ICollection<ClassStudent>` 集合属性,
// 用于表示该用户所注册的班级联结记录 (与 `ClassTeacherConfiguration` 中的模式类似)。
builder.HasOne(cs => cs.Student) // 当前 ClassStudent 链接到一个 User (学生)
.WithMany(u => u.EnrolledClassesLink) // 那个 User (学生) 可以有多个 ClassStudent 记录
.HasForeignKey(cs => cs.StudentId) // 外键是 ClassStudent.StudentId
.OnDelete(DeleteBehavior.Restrict); // 当 User (学生) 被删除时,如果还有相关的 ClassStudent 记录,则会阻止删除。
// 这是更安全的做法,以避免意外数据丢失。如果你希望学生被删除时,其所有注册关系也一并删除,可改为 DeleteBehavior.Cascade。
}
}
}

View File

@@ -1,61 +0,0 @@
using Entities.Contracts;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore;
namespace TechHelper.Context.Configuration
{
public class ClassTeacherConfiguration : IEntityTypeConfiguration<ClassTeacher>
{
public void Configure(EntityTypeBuilder<ClassTeacher> builder)
{
// 1. 设置表名
// 将此实体映射到数据库中名为 "class_teachers" 的表。
builder.ToTable("class_teachers");
// 2. 设置复合主键
// ClassId 和 TeacherId 的组合作为主键,确保一个班级中一个老师只有一条任教记录。
// 这要求 ClassTeacher 类中的 ClassId 和 TeacherId 属性上都添加了 [Key] 特性。
builder.HasKey(ct => new { ct.ClassId, ct.TeacherId });
// 3. 配置列名和属性特性
// 配置 ClassId 属性对应的数据库列名为 "class_id"。
builder.Property(ct => ct.ClassId)
.HasColumnName("class_id");
// 配置 TeacherId 属性对应的数据库列名为 "teacher_id"。
builder.Property(ct => ct.TeacherId)
.HasColumnName("teacher_id");
// 配置 SubjectTaught 属性对应的数据库列名为 "subject_taught"。
// 假设 SubjectTaught 可以为空,所以没有 .IsRequired()
builder.Property(ct => ct.SubjectTaught)
.HasColumnName("subject_taught");
// 4. 配置导航属性和外键关系
// ---
// 配置 ClassTeacher 到 Class 的关系 (多对一)
// 一个 ClassTeacher 联结记录属于一个 Class。
//
// 假设 `Class` 实体中有一个名为 `ClassTeachers` 的 `ICollection<ClassTeacher>` 集合属性。
builder.HasOne(ct => ct.Class) // 当前 ClassTeacher 链接到一个 Class
.WithMany(c => c.ClassTeachers) // 那个 Class 可以有多个 ClassTeacher 记录
.HasForeignKey(ct => ct.ClassId) // 外键是 ClassTeacher.ClassId
.OnDelete(DeleteBehavior.Cascade); // 当 Class 被删除时,相关的 ClassTeacher 记录也级联删除。
// ---
// 配置 ClassTeacher 到 User (Teacher) 的关系 (多对一)
// 一个 ClassTeacher 联结记录属于一个 User (作为 Teacher)。
//
// 假设 `User` 实体中有一个名为 `TaughtClassesLink` 的 `ICollection<ClassTeacher>` 集合属性,
// 用于表示该用户所教授的班级联结记录。
builder.HasOne(ct => ct.Teacher) // 当前 ClassTeacher 链接到一个 User (老师)
.WithMany(u => u.TaughtClassesLink) // 那个 User (老师) 可以有多个 ClassTeacher 记录 (为所教授的班级)
.HasForeignKey(ct => ct.TeacherId) // 外键是 ClassTeacher.TeacherId
.OnDelete(DeleteBehavior.Cascade); // 当 User (老师) 被删除时,如果还有相关的 ClassTeacher 记录,则会阻止删除。
// 这通常是防止数据丢失的更安全选择。如果你希望老师被删除时,其所有任教关系也一并删除,可改为 DeleteBehavior.Cascade。
}
}
}

View File

@@ -95,7 +95,7 @@ namespace TechHelper.Context.Configuration
//
// 这个关系的外键配置通常在 "多" 的一方(`AssignmentQuestion` 实体)进行。
// 假设 `AssignmentQuestion` 实体有一个 `QuestionId` 外键和 `Question` 导航属性。
builder.HasMany(q => q.AssignmentQuestions) // 当前 Question 有多个 AssignmentQuestion
builder.HasMany(q => q.ExamQuestions) // 当前 Question 有多个 AssignmentQuestion
.WithOne(aq => aq.Question); // 每一个 AssignmentQuestion 都有一个 Question
// .HasForeignKey(aq => aq.QuestionId); // 外键的配置应在 `AssignmentQuestionConfiguration` 中进行

View File

@@ -21,7 +21,7 @@ namespace TechHelper.Context.Configuration
.HasColumnName("id");
// AssignmentId
builder.Property(s => s.AssignmentId)
builder.Property(s => s.ExamId)
.HasColumnName("assignment_id")
.IsRequired();
@@ -67,9 +67,9 @@ namespace TechHelper.Context.Configuration
builder.HasOne(s => s.Assignment) // 当前 Submission 有一个 Assignment
builder.HasOne(s => s.Exam) // 当前 Submission 有一个 Assignment
.WithMany(a => a.Submissions) // 那个 Assignment 可以有多个 Submission
.HasForeignKey(s => s.AssignmentId) // 外键是 Submission.AssignmentId
.HasForeignKey(s => s.ExamId) // 外键是 Submission.AssignmentId
.OnDelete(DeleteBehavior.Cascade); // 当 Assignment 被删除时,相关的 Submission 也级联删除。

View File

@@ -23,7 +23,7 @@ namespace TechHelper.Context.Configuration
.HasColumnName("student_id")
.IsRequired();
builder.Property(sd => sd.AssignmentQuestionId)
builder.Property(sd => sd.ExamQuestionId)
.HasColumnName("assignment_question_id")
.IsRequired();
@@ -67,9 +67,9 @@ namespace TechHelper.Context.Configuration
.OnDelete(DeleteBehavior.Cascade); // 当 User (学生) 被删除时,如果他/她还有提交详情,则会阻止删除。
// 这是一个更安全的选择,以防止意外数据丢失。
builder.HasOne(sd => sd.AssignmentQuestion) // 当前 SubmissionDetail 有一个 AssignmentQuestion
builder.HasOne(sd => sd.ExamQuestion) // 当前 SubmissionDetail 有一个 AssignmentQuestion
.WithMany(aq => aq.SubmissionDetails) // 那个 AssignmentQuestion 可以有多个 SubmissionDetail 记录
.HasForeignKey(sd => sd.AssignmentQuestionId) // 外键是 SubmissionDetail.AssignmentQuestionId
.HasForeignKey(sd => sd.ExamQuestionId) // 外键是 SubmissionDetail.AssignmentQuestionId
.OnDelete(DeleteBehavior.Cascade); // 当 AssignmentQuestion 被删除时,相关的 SubmissionDetail 记录也级联删除。
}
}

View File

@@ -38,7 +38,7 @@ namespace TechHelper.Context.Configuration
.OnDelete(DeleteBehavior.Restrict); // 限制删除:如果创建者有题目,则不允许删除
// User 作为创建者,与 Assignment 的关系 (一对多)
builder.HasMany(u => u.CreatedAssignments) // 一个 User 可以创建多个作业
builder.HasMany(u => u.CreatedExams) // 一个 User 可以创建多个作业
.WithOne(a => a.Creator) // 一个 Assignment 对应一个 Creator
.HasForeignKey(a => a.CreatorId) // 外键在 Assignment.CreatedBy
.OnDelete(DeleteBehavior.Restrict); // 限制删除:如果创建者有作业,则不允许删除

View File

@@ -0,0 +1,22 @@
using Entities.Contracts;
using Microsoft.AspNetCore.Identity;
namespace TechHelper.Server.Context
{
public class DbInitializer
{
public static async Task SeedRoles(RoleManager<IdentityRole<Guid>> roleManager)
{
string[] defaultRoleName = { "Admin", "Teacher", "Student" };
foreach (var roleName in defaultRoleName)
{
if (!await roleManager.RoleExistsAsync(roleName))
{
await roleManager.CreateAsync(new IdentityRole<Guid>(roleName));
Console.WriteLine($"Default role '{roleName}' created successfully.");
}
}
}
}
}

View File

@@ -1,12 +1,10 @@
using TechHelper.Context;
using TechHelper.Services;
using Entities.DTO;
using Microsoft.AspNetCore.Http;
using Entities.DTO;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using TechHelper.Features;
using Microsoft.AspNetCore.WebUtilities;
using Entities.Contracts;
using TechHelper.Services.Beta;
namespace TechHelper.Controllers
{
@@ -19,9 +17,9 @@ namespace TechHelper.Controllers
public class AccountController : ControllerBase
{
private readonly UserManager<User> _userManager;
private readonly IUserRegistrationService _userRegistrationService;
private IAuthenticationService _authenticationService;
private readonly IEmailSender _emailSender;
private readonly IUserSerivces _userSerivces;
/// <summary>
/// 初始化账户控制器
@@ -31,13 +29,13 @@ namespace TechHelper.Controllers
/// <param name="emailSender">邮件发送服务</param>
/// <param name="authenticationService">认证服务</param>
public AccountController(UserManager<User> userManager,
IUserRegistrationService userRegistrationService,
IEmailSender emailSender,
IUserSerivces userSerivces,
IAuthenticationService authenticationService)
{
_userManager = userManager;
this._userRegistrationService = userRegistrationService;
_emailSender = emailSender;
_userSerivces = userSerivces;
_authenticationService = authenticationService;
}
@@ -98,7 +96,7 @@ namespace TechHelper.Controllers
if (!ModelState.IsValid)
return BadRequest(new ApiResponse(false, ModelState));
var response = await _userRegistrationService.RegisterNewUserAsync(userForRegistrationDto);
var response = await _userSerivces.RegisterNewUserAsync(userForRegistrationDto);
if (response.Status)
{
@@ -184,6 +182,17 @@ namespace TechHelper.Controllers
});
}
[HttpPost("initadmin")]
public async Task<IActionResult> InitAdmin([FromBody] UserForAdmin admin)
{
var result = await _userSerivces.InitAdminUser(admin);
if(result.Status)
{
return Ok(result.Message);
}
return BadRequest(result.Message);
}
/// <summary>
/// 生成两步验证的OTP令牌
/// </summary>

View File

@@ -1,11 +1,15 @@
using Entities.Contracts;
using Entities.DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Net;
using System.Security.Claims;
using TechHelper.Services.Beta;
using TechHelper.Services;
using Entities.DTO.Class;
namespace TechHelper.Server.Controllers
{
@@ -17,7 +21,7 @@ namespace TechHelper.Server.Controllers
[ApiController]
public class ClassController : ControllerBase
{
private IClassService _classService;
private TechHelper.Services.Beta.IClassService _classService;
private UserManager<User> _userManager;
/// <summary>
@@ -25,12 +29,159 @@ namespace TechHelper.Server.Controllers
/// </summary>
/// <param name="classService">班级服务</param>
/// <param name="userManager">用户管理服务</param>
public ClassController(IClassService classService, UserManager<User> userManager)
public ClassController(TechHelper.Services.Beta.IClassService classService, UserManager<User> userManager)
{
_classService = classService;
_userManager = userManager;
}
#region CRUD操作
/// <summary>
/// 获取班级列表(支持搜索)
/// </summary>
/// <param name="query">查询参数</param>
/// <returns>班级列表</returns>
/// <response code="200">成功获取班级列表</response>
/// <response code="400">获取失败</response>
[HttpGet]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetAll([FromQuery] QueryParameter query)
{
var result = await _classService.GetAllAsync(query);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 根据ID获取班级详细信息
/// </summary>
/// <param name="id">班级ID</param>
/// <returns>班级详细信息</returns>
/// <response code="200">成功获取班级信息</response>
/// <response code="400">班级未找到或获取失败</response>
[HttpGet("{id}")]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await _classService.GetAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 创建新班级
/// </summary>
/// <param name="model">班级数据传输对象</param>
/// <returns>创建结果</returns>
/// <response code="200">创建成功</response>
/// <response code="400">创建失败</response>
[HttpPost]
public async Task<IActionResult> Create([FromBody] ClassDto model)
{
var result = await _classService.AddAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
[HttpPost("AdminCreate")]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Create([FromBody] ClassCreateDto dto)
{
var result = await _classService.AdminAddAsync(dto);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 更新班级信息
/// </summary>
/// <param name="model">班级数据传输对象</param>
/// <returns>更新结果</returns>
/// <response code="200">更新成功</response>
/// <response code="400">更新失败</response>
[HttpPut]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Update([FromBody] ClassDto model)
{
var result = await _classService.UpdateAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 删除班级
/// </summary>
/// <param name="id">班级ID</param>
/// <returns>删除结果</returns>
/// <response code="200">删除成功</response>
/// <response code="400">删除失败</response>
[HttpDelete("{id}")]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Delete(Guid id)
{
var result = await _classService.DeleteAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Message);
}
#endregion
#region
/// <summary>
/// 验证班级信息是否存在
/// </summary>
/// <param name="toClass">包含学校名称、年级和班级名称的数据传输对象</param>
/// <returns>验证结果和班级信息</returns>
/// <response code="200">验证成功,返回班级信息</response>
/// <response code="400">验证失败</response>
[HttpPost("validate")]
[Authorize(Roles = "Student,Teacher,Admin")]
public async Task<IActionResult> ValidateClassInfo(
[FromBody] ClassValidDto toClass)
{
var result = await _classService.ValidateClassRegistration(toClass);
if (!result.Status) return BadRequest(result.Message);
return Ok(result.Result);
}
/// <summary>
/// 用户注册到班级
/// </summary>
@@ -39,107 +190,68 @@ namespace TechHelper.Server.Controllers
/// <response code="200">注册成功</response>
/// <response code="400">注册失败</response>
[HttpPost("userRegiste")]
[Authorize(Roles = "Student,Teacher,Admin")]
public async Task<IActionResult> UserRegisterToClass(
[FromBody] UserRegistrationToClassDto toClass)
[FromBody] RegisterUserToClassDto toClass)
{
var result = await _classService.UserRegister(toClass);
if (!result.Status) return BadRequest(result.Message);
return Ok();
return Ok(result.Message);
}
/// <summary>
/// 获取班级学生列表
/// 仅限教师角色访问,根据教师所在班级信息获取学生列表
/// 根据班级ID获取班级学生列表
/// </summary>
/// <param name="classId">班级ID</param>
/// <returns>班级学生列表</returns>
/// <response code="200">成功获取学生列表</response>
/// <response code="400">权限不足或班级信息缺失</response>
[HttpPost("getClassStudents")]
public async Task<IActionResult> GetClassStudents()
/// <response code="400">班级未找到或获取失败</response>
[HttpGet("students/{classId}")]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetClassStudentsById(Guid classId)
{
if (User.IsInRole("Teacher"))
var result = await _classService.GetClassStudentsAsync(classId);
if (!result.Status)
{
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);
return BadRequest(result.Message);
}
else
{
return BadRequest("你没有权限查看,未识别到你的教师身份。");
}
}
/// <summary>
/// 创建新班级
/// </summary>
/// <param name="classDto">班级数据传输对象</param>
/// <returns>操作结果</returns>
/// <response code="200">班级创建成功</response>
/// <response code="400">班级创建失败</response>
[HttpPost("Create")]
public async Task<IActionResult> Create(
[FromBody] ClassDto classDto)
{
var result = await _classService.AddAsync(classDto);
if (!result.Status) return BadRequest(result.Message);
return Ok();
}
/// <summary>
/// 获取指定年级的所有班级列表
/// </summary>
/// <param name="classDto">年级编号</param>
/// <returns>班级列表</returns>
/// <response code="200">成功获取班级列表</response>
/// <response code="400">获取失败</response>
[HttpPost("GetGradeClasses")]
public async Task<IActionResult> GetGradeClasses(
[FromBody] byte classDto)
{
var result = await _classService.GetGradeClasses(classDto);
if (!result.Status) return BadRequest(result.Message);
return Ok(result.Result);
}
[HttpGet("classes")]
[Authorize(Roles = "Teacher, Student")]
public async Task<IActionResult> GetUserInjoinedClass()
{
var user = await _userManager.FindByEmailAsync(User.Identity.Name);
var userid = user.Id;
var result = await _classService.GetUserInjoinedClasses(userid);
if (result.Status)
return Ok(result.Result);
else
return BadRequest(result.Message);
}
[HttpGet("injoint/{id:guid}")]
[Authorize(Roles = "Teacher, Student")]
public async Task<IActionResult> InjoinClass(Guid id)
{
var user = await _userManager.FindByEmailAsync(User.Identity.Name);
var userid = user.Id;
var registerClass = new RegisterUserToClassDto { ClassId = id, UserId = userid, Role = user.Role ?? UserRoles.Student };
var result = await _classService.UserRegister(registerClass);
if (result.Status)
return Ok(result.Result);
else
return BadRequest(result.Message);
}
#endregion
}
}

View File

@@ -0,0 +1,28 @@
using Entities.Contracts;
using Entities.DTO;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
namespace TechHelper.Server.Controllers
{
[Route("api/common")]
[ApiController]
public class CommonController : Controller
{
private readonly UserManager<User> _userManager;
public CommonController(UserManager<User> userManager)
{
_userManager = userManager;
}
[HttpGet("GetCommonType")]
public IActionResult GetCommonType(TypeCommonRequest typeCommon)
{
return Ok();
}
}
}

View File

@@ -4,9 +4,8 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using TechHelper.Server.Services;
using System.Security.Claims;
using TechHelper.Services;
using TechHelper.Services.Beta;
namespace TechHelper.Server.Controllers
@@ -30,13 +29,14 @@ namespace TechHelper.Server.Controllers
/// </summary>
/// <param name="examDto">考试/作业的数据传输对象。</param>
/// <returns>新创建的考试/作业信息或错误信息。</returns>
[HttpPost("add")]
public async Task<IActionResult> AddExam([FromBody] AssignmentDto examDto)
[HttpPost()]
[Authorize(Roles = "Teacher")]
public async Task<IActionResult> AddExam([FromBody] ExamDto examDto)
{
var user = await _userManager.FindByEmailAsync(User.Identity.Name);
if (user == null) return NotFound("没有找到用户");
examDto.CreatorId = user.Id;
var result = await _examService.CreateExamAsync(examDto);
var result = await _examService.AddAsync(examDto);
if (result.Status)
{
@@ -48,17 +48,12 @@ namespace TechHelper.Server.Controllers
}
}
/// <summary>
/// 提交作业。
/// </summary>
/// <param name="submissionDto">提交的数据传输对象。</param>
/// <returns>提交结果或错误信息。</returns>
[HttpPost("submission")]
public async Task<IActionResult> SubmissionAssignment([FromBody] SubmissionDto submissionDto)
[HttpGet]
public async Task<IActionResult> GetAllExams([FromQuery] QueryParameter queryParameter)
{
var result = await _examService.SubmissionAssignment(submissionDto);
var result = await _examService.GetAllAsync(queryParameter);
if (result.Status)
if(result.Status)
{
return Ok(result.Result);
}
@@ -96,70 +91,7 @@ namespace TechHelper.Server.Controllers
}
}
/// <summary>
/// 获取所有考试/作业的预览信息(教师获取自己创建的,学生获取自己需要提交的)。
/// </summary>
/// <returns>考试/作业预览列表或错误信息。</returns>
[HttpGet("getAllPreview")]
public async Task<IActionResult> GetAllExamPreview()
{
var user = await _userManager.FindByEmailAsync(User.Identity.Name);
if (user == null) return NotFound("没有找到用户");
ApiResponse result;
if (User.IsInRole("Teacher"))
{
result = await _examService.GetAllExamPreviewsAsync(user.Id);
}
else if (User.IsInRole("Student"))
{
result = await _examService.GetAllSubmissionAsync(user.Id);
}
else
{
return Forbid("你没有查看考试预览的权限。");
}
if (result.Status)
{
return Ok(result.Result);
}
else
{
return BadRequest(result.Message);
}
}
/// <summary>
/// 获取学生的所有提交记录。
/// </summary>
/// <returns>提交记录列表或错误信息。</returns>
[HttpGet("getAllSubmissions")]
[Authorize(Roles = "Student")]
public async Task<IActionResult> GetAllSubmission()
{
var user = await _userManager.FindByEmailAsync(User.Identity.Name);
if (user == null) return NotFound("没有找到用户");
var result = await _examService.GetAllSubmissionAsync(user.Id);
if (result.Status)
{
return Ok(result.Result);
}
else
{
return BadRequest(result.Message);
}
}
/// <summary>
/// 逻辑删除指定ID的考试/作业。
/// </summary>
/// <param name="id">要删除的考试/作业ID。</param>
/// <returns>操作结果。</returns>
[HttpDelete("delete/{id:guid}")]
[HttpDelete("{id:guid}")]
[Authorize(Roles = "Teacher")]
public async Task<IActionResult> DeleteAsync(Guid id)
{
@@ -179,13 +111,32 @@ namespace TechHelper.Server.Controllers
}
}
[HttpPost("GetTotalDistributionInClass")]
[Authorize(Roles = "Teacher")]
public async Task<IActionResult> GetTotalDistributionInClass(AssigExamToClassDto dto)
{
var result = await _examService.GetExamTotalErrorDistributionInClassAsync(dto);
if (result.Status)
{
return Ok(result.Result);
}
else
{
if (result.Message.Contains("未找到") || result.Message.Contains("not found", StringComparison.OrdinalIgnoreCase))
{
return NotFound(result.Message);
}
return BadRequest(result.Message);
}
}
/// <summary>
/// 为指定学生指派作业
/// </summary>
/// <param name="AETSdto"></param>
/// <returns></returns>
[HttpPost("assignmentExamToStudent")]
[HttpPost("assignmentExamToStudents")]
[Authorize(Roles = "Teacher")]
public async Task<IActionResult> AssignmentExamToStudent([FromBody] AssigExamToStudentsDto AETSdto)
{
@@ -206,12 +157,28 @@ namespace TechHelper.Server.Controllers
/// </summary>
/// <param name="AETSdto"></param>
/// <returns></returns>
[HttpPost("assignmentExamToStudent/{id:guid}")]
[HttpPost("assignmentExamToClass")]
[Authorize(Roles = "Teacher")]
public async Task<IActionResult> AssignmentExamToAllStudentsAsync(Guid id)
public async Task<IActionResult> AssignmentExamToClassAsync([FromBody] AssigExamToClassDto AETSdto)
{
var user = await _userManager.FindByEmailAsync(User.Identity.Name ?? "");
var result = await _examService.AssignmentToAllStudentsAsync(id, user.Id);
var result = await _examService.AssignmentToClassAsync(user.Id, AETSdto.examId, AETSdto.classId);
if (result.Status)
{
return Ok(result.Result);
}
else
{
return BadRequest(result.Message);
}
}
[HttpGet("GetExamSubmissionDetailInClassAsync")]
public async Task<IActionResult> GetExamSubmissionDetailInClassAsync([FromBody] AssigExamToClassDto model)
{
var result = await _examService.GetExamSubmissionDetailInClassAsync(model);
if (result.Status)
{
return Ok(result.Result);

View File

@@ -0,0 +1,161 @@
using Entities.Contracts;
using Entities.DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Net;
using System.Security.Claims;
using TechHelper.Services;
using TechHelper.Services.Beta;
using static TechHelper.Services.Beta.IExamQuestionService;
namespace TechHelper.Server.Controllers
{
/// <summary>
/// 考试题目管理控制器
/// 处理考试题目相关的操作,如创建、更新、删除考试题目等
/// </summary>
[Route("api/exam-question")]
[ApiController]
public class ExamQuestionController : ControllerBase
{
private readonly IExamQuestionService _examQuestionService;
private readonly UserManager<User> _userManager;
/// <summary>
/// 初始化考试题目控制器
/// </summary>
/// <param name="examQuestionService">考试题目服务</param>
/// <param name="userManager">用户管理服务</param>
public ExamQuestionController(IExamQuestionService examQuestionService, UserManager<User> userManager)
{
_examQuestionService = examQuestionService;
_userManager = userManager;
}
#region CRUD操作
/// <summary>
/// 获取考试题目列表(支持搜索)
/// </summary>
/// <param name="query">查询参数</param>
/// <returns>考试题目列表</returns>
/// <response code="200">成功获取考试题目列表</response>
/// <response code="400">获取失败</response>
[HttpGet]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetAll([FromQuery] QueryParameter query)
{
var result = await _examQuestionService.GetAllAsync(query);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 根据ID获取考试题目详细信息
/// </summary>
/// <param name="id">考试题目ID</param>
/// <returns>考试题目详细信息</returns>
/// <response code="200">成功获取考试题目信息</response>
/// <response code="400">考试题目未找到或获取失败</response>
[HttpGet("{id}")]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await _examQuestionService.GetAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 创建新考试题目
/// </summary>
/// <param name="model">考试题目数据传输对象</param>
/// <returns>创建结果</returns>
/// <response code="200">创建成功</response>
/// <response code="400">创建失败</response>
[HttpPost]
[Authorize(Roles = "Admin,Teacher")]
public async Task<IActionResult> Create([FromBody] ExamQuestionDto model)
{
var result = await _examQuestionService.AddAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 更新考试题目信息
/// </summary>
/// <param name="model">考试题目数据传输对象</param>
/// <returns>更新结果</returns>
/// <response code="200">更新成功</response>
/// <response code="400">更新失败</response>
[HttpPut]
[Authorize(Roles = "Admin, Teacher")]
public async Task<IActionResult> Update([FromBody] ExamQuestionDto model)
{
var result = await _examQuestionService.UpdateAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 删除考试题目
/// </summary>
/// <param name="id">考试题目ID</param>
/// <returns>删除结果</returns>
/// <response code="200">删除成功</response>
/// <response code="400">删除失败</response>
[HttpDelete("{id}")]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Delete(Guid id)
{
var result = await _examQuestionService.DeleteAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Message);
}
#endregion
[HttpPost("GetQuestionDependy")]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetQuestionDependy(QuesitionDenpendceyRequst request)
{
var result = await _examQuestionService.GetQuestionDependy(request);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
}
}

View File

@@ -0,0 +1,145 @@
using Entities.Contracts;
using Entities.DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Net;
using System.Security.Claims;
using TechHelper.Services.Beta;
using TechHelper.Services;
namespace TechHelper.Server.Controllers
{
/// <summary>
/// 考试类型管理控制器
/// 处理考试类型相关的操作,如创建、更新、删除考试类型等
/// </summary>
[Route("api/exam-type")]
[ApiController]
public class ExamTypeController : ControllerBase
{
private readonly IExamTypeService _examTypeService;
private readonly UserManager<User> _userManager;
/// <summary>
/// 初始化考试类型控制器
/// </summary>
/// <param name="examTypeService">考试类型服务</param>
/// <param name="userManager">用户管理服务</param>
public ExamTypeController(IExamTypeService examTypeService, UserManager<User> userManager)
{
_examTypeService = examTypeService;
_userManager = userManager;
}
#region CRUD操作
/// <summary>
/// 获取考试类型列表(支持搜索)
/// </summary>
/// <param name="query">查询参数</param>
/// <returns>考试类型列表</returns>
/// <response code="200">成功获取考试类型列表</response>
/// <response code="400">获取失败</response>
[HttpGet]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetAll([FromQuery] QueryParameter query)
{
var result = await _examTypeService.GetAllAsync(query);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 根据ID获取考试类型详细信息
/// </summary>
/// <param name="id">考试类型ID</param>
/// <returns>考试类型详细信息</returns>
/// <response code="200">成功获取考试类型信息</response>
/// <response code="400">考试类型未找到或获取失败</response>
[HttpGet("{id}")]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await _examTypeService.GetAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 创建新考试类型
/// </summary>
/// <param name="model">考试类型数据传输对象</param>
/// <returns>创建结果</returns>
/// <response code="200">创建成功</response>
/// <response code="400">创建失败</response>
[HttpPost]
[Authorize(Roles = "Admin, Teacher")]
public async Task<IActionResult> Create([FromBody] ExamTypeDto model)
{
var result = await _examTypeService.AddAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 更新考试类型信息
/// </summary>
/// <param name="model">考试类型数据传输对象</param>
/// <returns>更新结果</returns>
/// <response code="200">更新成功</response>
/// <response code="400">更新失败</response>
[HttpPut]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Update([FromBody] ExamTypeDto model)
{
var result = await _examTypeService.UpdateAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 删除考试类型
/// </summary>
/// <param name="id">考试类型ID</param>
/// <returns>删除结果</returns>
/// <response code="200">删除成功</response>
/// <response code="400">删除失败</response>
[HttpDelete("{id}")]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Delete(Guid id)
{
var result = await _examTypeService.DeleteAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Message);
}
#endregion
}
}

View File

@@ -0,0 +1,144 @@
using Entities.Contracts;
using Entities.DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Net;
using System.Security.Claims;
using TechHelper.Services.Beta;
using TechHelper.Services;
namespace TechHelper.Server.Controllers
{
/// <summary>
/// 年级管理控制器
/// 处理年级相关的操作,如创建、更新、删除年级等
/// </summary>
[Route("api/grade")]
[ApiController]
public class GradeController : ControllerBase
{
private TechHelper.Services.Beta.IGradeService _gradeService;
private UserManager<User> _userManager;
/// <summary>
/// 初始化年级控制器
/// </summary>
/// <param name="gradeService">年级服务</param>
/// <param name="userManager">用户管理服务</param>
public GradeController(TechHelper.Services.Beta.IGradeService gradeService, UserManager<User> userManager)
{
_gradeService = gradeService;
_userManager = userManager;
}
#region CRUD操作
/// <summary>
/// 获取年级列表(支持搜索)
/// </summary>
/// <param name="query">查询参数</param>
/// <returns>年级列表</returns>
/// <response code="200">成功获取年级列表</response>
/// <response code="400">获取失败</response>
[HttpGet]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetAll([FromQuery] QueryParameter query)
{
var result = await _gradeService.GetAllAsync(query);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 根据ID获取年级详细信息
/// </summary>
/// <param name="id">年级ID</param>
/// <returns>年级详细信息</returns>
/// <response code="200">成功获取年级信息</response>
/// <response code="400">年级未找到或获取失败</response>
[HttpGet("{id}")]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await _gradeService.GetAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 创建新年级
/// </summary>
/// <param name="model">年级数据传输对象</param>
/// <returns>创建结果</returns>
/// <response code="200">创建成功</response>
/// <response code="400">创建失败</response>
[HttpPost]
public async Task<IActionResult> Create([FromBody] GradeDto model)
{
var result = await _gradeService.AddAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 更新年级信息
/// </summary>
/// <param name="model">年级数据传输对象</param>
/// <returns>更新结果</returns>
/// <response code="200">更新成功</response>
/// <response code="400">更新失败</response>
[HttpPut]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Update([FromBody] GradeDto model)
{
var result = await _gradeService.UpdateAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 删除年级
/// </summary>
/// <param name="id">年级ID</param>
/// <returns>删除结果</returns>
/// <response code="200">删除成功</response>
/// <response code="400">删除失败</response>
[HttpDelete("{id}")]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Delete(Guid id)
{
var result = await _gradeService.DeleteAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Message);
}
#endregion
}
}

View File

@@ -0,0 +1,167 @@
using Entities.Contracts;
using Entities.DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using TechHelper.Services;
using TechHelper.Services.Beta;
namespace TechHelper.Server.Controllers
{
/// <summary>
/// 知识点管理控制器
/// 处理知识点相关的操作,如创建、更新、删除知识点等
/// </summary>
[Route("api/keypoint")]
[ApiController]
public class KeyPointController : ControllerBase
{
private readonly IKeyPointService _keyPointService;
private readonly UserManager<User> _userManager;
/// <summary>
/// 初始化知识点控制器
/// </summary>
/// <param name="keyPointService">知识点服务</param>
/// <param name="userManager">用户管理服务</param>
public KeyPointController(IKeyPointService keyPointService, UserManager<User> userManager)
{
_keyPointService = keyPointService;
_userManager = userManager;
}
#region CRUD操作
/// <summary>
/// 获取知识点列表(支持搜索)
/// </summary>
/// <param name="query">查询参数</param>
/// <returns>知识点列表</returns>
/// <response code="200">成功获取知识点列表</response>
/// <response code="400">获取失败</response>
[HttpGet]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetAll([FromQuery] QueryParameter query)
{
var result = await _keyPointService.GetAllAsync(query);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 根据ID获取知识点详细信息
/// </summary>
/// <param name="id">知识点ID</param>
/// <returns>知识点详细信息</returns>
/// <response code="200">成功获取知识点信息</response>
/// <response code="400">知识点未找到或获取失败</response>
[HttpGet("{id}")]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await _keyPointService.GetAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 创建新知识点
/// </summary>
/// <param name="model">知识点数据传输对象</param>
/// <returns>创建结果</returns>
/// <response code="200">创建成功</response>
/// <response code="400">创建失败</response>
[HttpPost]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> Create([FromBody] KeyPointDto model)
{
var result = await _keyPointService.AddAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 更新知识点信息
/// </summary>
/// <param name="model">知识点数据传输对象</param>
/// <returns>更新结果</returns>
/// <response code="200">更新成功</response>
/// <response code="400">更新失败</response>
[HttpPut]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> Update([FromBody] KeyPointDto model)
{
var result = await _keyPointService.UpdateAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 删除知识点
/// </summary>
/// <param name="id">知识点ID</param>
/// <returns>删除结果</returns>
/// <response code="200">删除成功</response>
/// <response code="400">删除失败</response>
[HttpDelete("{id}")]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> Delete(Guid id)
{
var result = await _keyPointService.DeleteAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Message);
}
#endregion
#region
/// <summary>
/// 根据课程ID获取知识点列表
/// </summary>
/// <param name="lessonId">课程ID</param>
/// <returns>知识点列表</returns>
/// <response code="200">成功获取知识点列表</response>
/// <response code="400">获取失败</response>
[HttpGet("lesson/{lessonId}")]
[Authorize(Roles = "Student,Teacher,Admin")]
public async Task<IActionResult> GetByLessonId(Guid lessonId)
{
var result = await _keyPointService.GetKeyPointsByLessonIdAsync(lessonId);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
#endregion
}
}

View File

@@ -0,0 +1,167 @@
using Entities.Contracts;
using Entities.DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using TechHelper.Services;
using TechHelper.Services.Beta;
namespace TechHelper.Server.Controllers
{
/// <summary>
/// 课程管理控制器
/// 处理课程相关的操作,如创建、更新、删除课程等
/// </summary>
[Route("api/Lesson")]
[ApiController]
public class LessonController : ControllerBase
{
private readonly ILessonService _lessonService;
private readonly UserManager<User> _userManager;
/// <summary>
/// 初始化课程控制器
/// </summary>
/// <param name="lessonService">课程服务</param>
/// <param name="userManager">用户管理服务</param>
public LessonController(ILessonService lessonService, UserManager<User> userManager)
{
_lessonService = lessonService;
_userManager = userManager;
}
#region CRUD操作
/// <summary>
/// 获取课程列表(支持搜索)
/// </summary>
/// <param name="query">查询参数</param>
/// <returns>课程列表</returns>
/// <response code="200">成功获取课程列表</response>
/// <response code="400">获取失败</response>
[HttpGet]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetAll([FromQuery] QueryParameter query)
{
var result = await _lessonService.GetAllAsync(query);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 根据ID获取课程详细信息
/// </summary>
/// <param name="id">课程ID</param>
/// <returns>课程详细信息</returns>
/// <response code="200">成功获取课程信息</response>
/// <response code="400">课程未找到或获取失败</response>
[HttpGet("{id}")]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await _lessonService.GetAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 创建新课程
/// </summary>
/// <param name="model">课程数据传输对象</param>
/// <returns>创建结果</returns>
/// <response code="200">创建成功</response>
/// <response code="400">创建失败</response>
[HttpPost]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> Create([FromBody] LessonDto model)
{
var result = await _lessonService.AddAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 更新课程信息
/// </summary>
/// <param name="model">课程数据传输对象</param>
/// <returns>更新结果</returns>
/// <response code="200">更新成功</response>
/// <response code="400">更新失败</response>
[HttpPut]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> Update([FromBody] LessonDto model)
{
var result = await _lessonService.UpdateAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 删除课程
/// </summary>
/// <param name="id">课程ID</param>
/// <returns>删除结果</returns>
/// <response code="200">删除成功</response>
/// <response code="400">删除失败</response>
[HttpDelete("{id}")]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> Delete(Guid id)
{
var result = await _lessonService.DeleteAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Message);
}
#endregion
#region
/// <summary>
/// 根据教材ID获取课程列表
/// </summary>
/// <param name="textbookId">教材ID</param>
/// <returns>课程列表</returns>
/// <response code="200">成功获取课程列表</response>
/// <response code="400">获取失败</response>
[HttpGet("textbook/{textbookId}")]
[Authorize(Roles = "Student,Teacher,Admin")]
public async Task<IActionResult> GetByTextbookId(Guid textbookId)
{
var result = await _lessonService.GetAllAsync(new QueryParameter { Search = textbookId.ToString() });
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
#endregion
}
}

View File

@@ -1,91 +0,0 @@
using Entities.DTO;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using TechHelper.Services;
namespace TechHelper.Server.Controllers
{
[Route("api/note")]
[ApiController]
public class NoteController : ControllerBase
{
private readonly INoteService _noteService;
// 通过依赖注入获取 NoteService
public NoteController(INoteService noteService)
{
_noteService = noteService;
}
/// <summary>
/// 获取所有全局数据。
/// GET: api/Note
/// </summary>
[HttpGet]
public async Task<IActionResult> GetAll([FromQuery] QueryParameter query)
{
var response = await _noteService.GetAllAsync(query);
return Ok(response);
}
/// <summary>
/// 根据 ID 获取单个全局数据。
/// GET: api/Note/{id}
/// </summary>
[HttpGet("{id}")]
public async Task<IActionResult> Get(byte id)
{
var response = await _noteService.GetAsync(id);
if (!response.Status)
{
return NotFound(response);
}
return Ok(response);
}
/// <summary>
/// 添加新的全局数据。
/// POST: api/Note
/// </summary>
[HttpPost]
public async Task<IActionResult> Add([FromBody] GlobalDto model)
{
var response = await _noteService.AddAsync(model);
if (!response.Status)
{
return BadRequest(response);
}
return Ok(response);
}
/// <summary>
/// 更新已存在的全局数据。
/// PUT: api/Note
/// </summary>
[HttpPut]
public async Task<IActionResult> Update([FromBody] GlobalDto model)
{
var response = await _noteService.UpdateAsync(model);
if (!response.Status)
{
return NotFound(response);
}
return Ok(response);
}
/// <summary>
/// 根据 ID 删除全局数据。
/// DELETE: api/Note/{id}
/// </summary>
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(byte id)
{
var response = await _noteService.DeleteAsync(id);
if (!response.Status)
{
return NotFound(response);
}
return Ok(response);
}
}
}

View File

@@ -0,0 +1,188 @@
using Entities.Contracts;
using Entities.DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using TechHelper.Services;
using TechHelper.Services.Beta;
namespace TechHelper.Server.Controllers
{
/// <summary>
/// 题目管理控制器
/// 处理题目相关的操作如CRUD、按标题查找等
/// </summary>
[Route("api/question")]
[ApiController]
public class QuestionController : ControllerBase
{
private readonly IQuestionService _questionService;
private readonly UserManager<User> _userManager;
/// <summary>
/// 初始化题目控制器
/// </summary>
/// <param name="questionService">题目服务</param>
/// <param name="userManager">用户管理服务</param>
public QuestionController(IQuestionService questionService, UserManager<User> userManager)
{
_questionService = questionService;
_userManager = userManager;
}
#region CRUD操作
/// <summary>
/// 获取题目列表(支持搜索和分页)
/// </summary>
/// <param name="query">查询参数</param>
/// <returns>题目列表</returns>
/// <response code="200">成功获取题目列表</response>
/// <response code="400">获取失败</response>
[HttpGet]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetAll([FromQuery] QueryParameter query)
{
var result = await _questionService.GetAllAsync(query);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 根据ID获取题目详细信息
/// </summary>
/// <param name="id">题目ID</param>
/// <returns>题目详细信息</returns>
/// <response code="200">成功获取题目信息</response>
/// <response code="400">题目未找到或获取失败</response>
[HttpGet("{id}")]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await _questionService.GetAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 创建新题目
/// </summary>
/// <param name="model">题目数据传输对象</param>
/// <returns>创建结果</returns>
/// <response code="200">创建成功</response>
/// <response code="400">创建失败</response>
[HttpPost]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> Create([FromBody] QuestionDto model)
{
var result = await _questionService.AddAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 更新题目信息
/// </summary>
/// <param name="model">题目数据传输对象</param>
/// <returns>更新结果</returns>
/// <response code="200">更新成功</response>
/// <response code="400">更新失败</response>
[HttpPut]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> Update([FromBody] QuestionDto model)
{
var result = await _questionService.UpdateAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 删除题目(软删除)
/// </summary>
/// <param name="id">题目ID</param>
/// <returns>删除结果</returns>
/// <response code="200">删除成功</response>
/// <response code="400">删除失败</response>
[HttpDelete("{id}")]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Delete(Guid id)
{
var result = await _questionService.DeleteAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Message);
}
#endregion
#region
/// <summary>
/// 根据标题查找题目
/// </summary>
/// <param name="title">题目标题</param>
/// <returns>题目信息</returns>
/// <response code="200">成功找到题目</response>
/// <response code="400">题目未找到或查找失败</response>
[HttpGet("by-title/{title}")]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetByTitle(string title)
{
var result = await _questionService.FindByTitle(title);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 批量检查题目标题是否存在
/// </summary>
/// <param name="titles">题目标题集合</param>
/// <returns>标题存在性检查结果</returns>
/// <response code="200">检查成功</response>
/// <response code="400">检查失败</response>
[HttpPost("check-titles")]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> CheckTitlesExistence([FromBody] List<string> titles)
{
var result = await _questionService.CheckTitlesExistence(titles);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
#endregion
}
}

View File

@@ -0,0 +1,145 @@
using Entities.Contracts;
using Entities.DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Net;
using System.Security.Claims;
using TechHelper.Services.Beta;
using TechHelper.Services;
namespace TechHelper.Server.Controllers
{
/// <summary>
/// 题型管理控制器
/// 处理题型相关的操作,如创建、更新、删除题型等
/// </summary>
[Route("api/question-type")]
[ApiController]
public class QuestionTypeController : ControllerBase
{
private readonly IQuestionTypeService _questionTypeService;
private readonly UserManager<User> _userManager;
/// <summary>
/// 初始化题型控制器
/// </summary>
/// <param name="questionTypeService">题型服务</param>
/// <param name="userManager">用户管理服务</param>
public QuestionTypeController(IQuestionTypeService questionTypeService, UserManager<User> userManager)
{
_questionTypeService = questionTypeService;
_userManager = userManager;
}
#region CRUD操作
/// <summary>
/// 获取题型列表(支持搜索)
/// </summary>
/// <param name="query">查询参数</param>
/// <returns>题型列表</returns>
/// <response code="200">成功获取题型列表</response>
/// <response code="400">获取失败</response>
[HttpGet]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetAll([FromQuery] QueryParameter query)
{
var result = await _questionTypeService.GetAllAsync(query);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 根据ID获取题型详细信息
/// </summary>
/// <param name="id">题型ID</param>
/// <returns>题型详细信息</returns>
/// <response code="200">成功获取题型信息</response>
/// <response code="400">题型未找到或获取失败</response>
[HttpGet("{id}")]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await _questionTypeService.GetAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 创建新题型
/// </summary>
/// <param name="model">题型数据传输对象</param>
/// <returns>创建结果</returns>
/// <response code="200">创建成功</response>
/// <response code="400">创建失败</response>
[HttpPost]
[Authorize(Roles = "Admin, Teacher")]
public async Task<IActionResult> Create([FromBody] QuestionTypeDto model)
{
var result = await _questionTypeService.AddAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 更新题型信息
/// </summary>
/// <param name="model">题型数据传输对象</param>
/// <returns>更新结果</returns>
/// <response code="200">更新成功</response>
/// <response code="400">更新失败</response>
[HttpPut]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Update([FromBody] QuestionTypeDto model)
{
var result = await _questionTypeService.UpdateAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 删除题型
/// </summary>
/// <param name="id">题型ID</param>
/// <returns>删除结果</returns>
/// <response code="200">删除成功</response>
/// <response code="400">删除失败</response>
[HttpDelete("{id}")]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Delete(Guid id)
{
var result = await _questionTypeService.DeleteAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Message);
}
#endregion
}
}

View File

@@ -0,0 +1,161 @@
using Entities.Contracts;
using Entities.DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using TechHelper.Services;
namespace TechHelper.Server.Controllers
{
/// <summary>
/// 学校管理控制器
/// 处理学校相关的操作,如创建、更新、删除学校等
/// </summary>
[Route("api/school")]
[ApiController]
public class SchoolController : ControllerBase
{
private TechHelper.Services.Beta.ISchoolService _schoolService;
private UserManager<User> _userManager;
/// <summary>
/// 初始化学校控制器
/// </summary>
/// <param name="schoolService">学校服务</param>
/// <param name="userManager">用户管理服务</param>
public SchoolController(TechHelper.Services.Beta.ISchoolService schoolService, UserManager<User> userManager)
{
_schoolService = schoolService;
_userManager = userManager;
}
#region CRUD操作
/// <summary>
/// 获取学校列表(支持搜索)
/// </summary>
/// <param name="query">查询参数</param>
/// <returns>学校列表</returns>
/// <response code="200">成功获取学校列表</response>
/// <response code="400">获取失败</response>
[HttpGet]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetAll([FromQuery] QueryParameter query)
{
var result = await _schoolService.GetAllAsync(query);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 根据ID获取学校详细信息
/// </summary>
/// <param name="id">学校ID</param>
/// <returns>学校详细信息</returns>
/// <response code="200">成功获取学校信息</response>
/// <response code="400">学校未找到或获取失败</response>
[HttpGet("{id}")]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await _schoolService.GetAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 创建新学校
/// </summary>
/// <param name="model">学校数据传输对象</param>
/// <returns>创建结果</returns>
/// <response code="200">创建成功</response>
/// <response code="400">创建失败</response>
[HttpPost]
public async Task<IActionResult> Create([FromBody] SchoolDto model)
{
var result = await _schoolService.AddAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 更新学校信息
/// </summary>
/// <param name="model">学校数据传输对象</param>
/// <returns>更新结果</returns>
/// <response code="200">更新成功</response>
/// <response code="400">更新失败</response>
[HttpPut]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Update([FromBody] SchoolDto model)
{
var result = await _schoolService.UpdateAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 删除学校
/// </summary>
/// <param name="id">学校ID</param>
/// <returns>删除结果</returns>
/// <response code="200">删除成功</response>
/// <response code="400">删除失败</response>
[HttpDelete("{id}")]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Delete(Guid id)
{
var result = await _schoolService.DeleteAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Message);
}
/// <summary>
/// 根据学校名称获取学校信息
/// </summary>
/// <param name="schoolName">学校名称</param>
/// <returns>学校信息</returns>
/// <response code="200">成功获取学校信息</response>
/// <response code="400">学校未找到或获取失败</response>
[HttpGet("byname/{schoolName}")]
[Authorize(Roles = "Student,Teacher,Admin")]
public async Task<IActionResult> GetByName(string schoolName)
{
var result = await _schoolService.GetSchoolByNameAsync(schoolName);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
#endregion
}
}

View File

@@ -3,8 +3,7 @@ using Entities.DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using TechHelper.Server.Services;
using System.Security.Claims;
using TechHelper.Services.Beta;
namespace TechHelper.Server.Controllers
{
@@ -13,11 +12,11 @@ namespace TechHelper.Server.Controllers
[Authorize]
public class StudentSubmissionController : ControllerBase
{
private readonly IStudentSubmissionService _studentSubmissionService;
private readonly ISubmissionService _studentSubmissionService;
private readonly UserManager<User> _userManager;
public StudentSubmissionController(
IStudentSubmissionService studentSubmissionService,
ISubmissionService studentSubmissionService,
UserManager<User> userManager)
{
_studentSubmissionService = studentSubmissionService;
@@ -35,7 +34,7 @@ namespace TechHelper.Server.Controllers
if (user == null)
return NotFound("未找到用户信息");
var result = await _studentSubmissionService.GetStudentSubmissionsAsync(user.Id);
var result = await _studentSubmissionService.GetStudentSubmissionDetailAsync(user.Id);
if (result.Status)
{
@@ -64,7 +63,7 @@ namespace TechHelper.Server.Controllers
if (user == null)
return NotFound("未找到用户信息");
var result = await _studentSubmissionService.GetStudentSubmissionsPagedAsync(user.Id, pageNumber, pageSize);
var result = await _studentSubmissionService.GetStudentSubmissionSummariesAsync(user.Id);
if (result.Status)
{
@@ -85,7 +84,7 @@ namespace TechHelper.Server.Controllers
[Authorize(Roles = "Teacher")]
public async Task<IActionResult> GetStudentSubmissions(Guid studentId)
{
var result = await _studentSubmissionService.GetStudentSubmissionsAsync(studentId);
var result = await _studentSubmissionService.GetStudentSubmissionSummariesAsync(studentId);
if (result.Status)
{
@@ -112,7 +111,7 @@ namespace TechHelper.Server.Controllers
if (pageSize < 1) pageSize = 10;
if (pageSize > 100) pageSize = 100; // 限制最大页面大小
var result = await _studentSubmissionService.GetStudentSubmissionsPagedAsync(studentId, pageNumber, pageSize);
var result = await _studentSubmissionService.GetStudentSubmissionSummariesAsync(studentId);
if (result.Status)
{

View File

@@ -3,11 +3,11 @@ using Entities.DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using TechHelper.Server.Services;
using TechHelper.Context;
using TechHelper.Repository;
using SharedDATA.Api;
using System.Security.Claims;
using TechHelper.Services.Beta;
namespace TechHelper.Server.Controllers
{
@@ -16,12 +16,12 @@ namespace TechHelper.Server.Controllers
[Authorize]
public class StudentSubmissionDetailController : ControllerBase
{
private readonly IStudentSubmissionDetailService _studentSubmissionDetailService;
private readonly ISubmissionDetailService _studentSubmissionDetailService;
private readonly UserManager<User> _userManager;
private readonly IUnitOfWork _unitOfWork;
public StudentSubmissionDetailController(
IStudentSubmissionDetailService studentSubmissionDetailService,
ISubmissionDetailService studentSubmissionDetailService,
UserManager<User> userManager,
IUnitOfWork unitOfWork)
{
@@ -61,7 +61,7 @@ namespace TechHelper.Server.Controllers
return Forbid("您没有权限查看此提交记录");
}
var result = await _studentSubmissionDetailService.GetSubmissionDetailAsync(submissionId);
var result = await _studentSubmissionDetailService.GetBySubmissionIdAsync(submissionId);
if (result.Status)
{

View File

@@ -0,0 +1,145 @@
using Entities.Contracts;
using Entities.DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Net;
using System.Security.Claims;
using TechHelper.Services.Beta;
using TechHelper.Services;
namespace TechHelper.Server.Controllers
{
/// <summary>
/// 科目管理控制器
/// 处理科目相关的操作,如创建、更新、删除科目等
/// </summary>
[Route("api/subject")]
[ApiController]
public class SubjectController : ControllerBase
{
private readonly ISubjectService _subjectService;
private readonly UserManager<User> _userManager;
/// <summary>
/// 初始化科目控制器
/// </summary>
/// <param name="subjectService">科目服务</param>
/// <param name="userManager">用户管理服务</param>
public SubjectController(ISubjectService subjectService, UserManager<User> userManager)
{
_subjectService = subjectService;
_userManager = userManager;
}
#region CRUD操作
/// <summary>
/// 获取科目列表(支持搜索)
/// </summary>
/// <param name="query">查询参数</param>
/// <returns>科目列表</returns>
/// <response code="200">成功获取科目列表</response>
/// <response code="400">获取失败</response>
[HttpGet]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetAll([FromQuery] QueryParameter query)
{
var result = await _subjectService.GetAllAsync(query);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 根据ID获取科目详细信息
/// </summary>
/// <param name="id">科目ID</param>
/// <returns>科目详细信息</returns>
/// <response code="200">成功获取科目信息</response>
/// <response code="400">科目未找到或获取失败</response>
[HttpGet("{id}")]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await _subjectService.GetAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 创建新科目
/// </summary>
/// <param name="model">科目数据传输对象</param>
/// <returns>创建结果</returns>
/// <response code="200">创建成功</response>
/// <response code="400">创建失败</response>
[HttpPost]
[Authorize(Roles = "Admin,Teacher")]
public async Task<IActionResult> Create([FromBody] SubjectDto model)
{
var result = await _subjectService.AddAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 更新科目信息
/// </summary>
/// <param name="model">科目数据传输对象</param>
/// <returns>更新结果</returns>
/// <response code="200">更新成功</response>
/// <response code="400">更新失败</response>
[HttpPut]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Update([FromBody] SubjectDto model)
{
var result = await _subjectService.UpdateAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 删除科目
/// </summary>
/// <param name="id">科目ID</param>
/// <returns>删除结果</returns>
/// <response code="200">删除成功</response>
/// <response code="400">删除失败</response>
[HttpDelete("{id}")]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Delete(Guid id)
{
var result = await _subjectService.DeleteAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Message);
}
#endregion
}
}

View File

@@ -4,8 +4,8 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using TechHelper.Server.Services;
using TechHelper.Services;
using TechHelper.Services.Beta;
namespace TechHelper.Server.Controllers
{
@@ -16,15 +16,16 @@ namespace TechHelper.Server.Controllers
public class SubmissionController : ControllerBase
{
private readonly UserManager<User> _userManager;
private readonly ISubmissionServices _submissionServices;
private readonly ISubmissionService _submissionServices;
public SubmissionController(UserManager<User> userManager, ISubmissionServices submissionServices)
public SubmissionController(UserManager<User> userManager, ISubmissionService submissionServices)
{
_userManager = userManager;
_submissionServices = submissionServices;
}
/// <summary>
/// 获取当前用户的所有错题。
/// </summary>
@@ -35,7 +36,7 @@ namespace TechHelper.Server.Controllers
var user = await _userManager.FindByEmailAsync(User.Identity.Name);
if (user == null)
{
return NotFound("未找到当前用户信息。");
return NotFound("未找到当前用户信息。");
}
var result = await _submissionServices.GetAllErrorQuestionsAsync(user.Id);
@@ -55,7 +56,7 @@ namespace TechHelper.Server.Controllers
/// </summary>
/// <param name="assignmentId">作业ID。</param>
/// <returns>错题列表或错误信息。</returns>
[HttpGet("getAssignmentErrorQuestions/{assignmentId:guid}")]
[HttpGet("getAssignmentErrorQuestions/{assignmentId:guid}")]
public async Task<IActionResult> GetAssignmentErrorQuestionsAsync(Guid assignmentId)
{
var user = await _userManager.FindByEmailAsync(User.Identity.Name);
@@ -138,7 +139,7 @@ namespace TechHelper.Server.Controllers
/// <param name="assignmentId">作业ID。</param>
/// <returns>按题目分组的学生错题列表。</returns>
[HttpGet("getQuestionErrorStudents/{assignmentId:guid}")]
[Authorize(Roles = "Teacher")]
[Authorize(Roles = "Teacher")]
public async Task<IActionResult> GetQuestionErrorStudents(Guid assignmentId)
{
var result = await _submissionServices.GetQuestionErrorStudents(assignmentId);
@@ -158,8 +159,8 @@ namespace TechHelper.Server.Controllers
/// </summary>
/// <param name="model">提交的数据模型。</param>
/// <returns>新创建的提交记录或错误信息。</returns>
[HttpPost("add")]
public async Task<IActionResult> AddAsync([FromBody] Submission model)
[HttpPost()]
public async Task<IActionResult> AddAsync([FromBody] SubmissionDto model)
{
// 可以在这里获取当前用户ID并赋值给 model.StudentId确保提交人信息正确
// var user = await _userManager.FindByEmailAsync(User.Identity.Name);
@@ -209,7 +210,7 @@ namespace TechHelper.Server.Controllers
/// </summary>
/// <param name="query">查询参数,包含分页信息。</param>
/// <returns>分页的提交记录列表。</returns>
[HttpGet("getAll")]
[HttpGet()]
[Authorize(Roles = "Admin,Teacher")]
public async Task<IActionResult> GetAllAsync([FromQuery] QueryParameter query)
{
@@ -252,7 +253,7 @@ namespace TechHelper.Server.Controllers
/// <param name="model">要更新的提交数据。</param>
/// <returns>更新后的提交记录或错误信息。</returns>
[HttpPut("update/{id:guid}")]
public async Task<IActionResult> UpdateAsync(Guid id, [FromBody] Submission model)
public async Task<IActionResult> UpdateAsync(Guid id, [FromBody] SubmissionDto model)
{
if (id != model.Id) // 确保路径中的ID和模型中的ID一致
{
@@ -275,5 +276,90 @@ namespace TechHelper.Server.Controllers
return BadRequest(result.Message);
}
}
[HttpPost("GradeExam")]
[Authorize(Roles = "Teacher")]
public async Task<IActionResult> GradeExam([FromBody] SubmissionTeacherUpdateDto model)
{
var result = await _submissionServices.GradeExam(model);
if (result.Status)
{
return Ok(result);
}
else
{
return BadRequest(result.Message);
}
}
/// <summary>
/// 获取学生提交摘要。
/// </summary>
/// <param name="userId">用户ID。</param>
/// <returns>学生提交摘要列表或错误信息。</returns>
[HttpGet("getStudentSubmissionSummaries")]
[Authorize(Roles = "Student")]
public async Task<IActionResult> GetStudentSubmissionSummariesAsync()
{
var user = await _userManager.FindByEmailAsync(User.Identity.Name);
if (user == null)
{
return NotFound("未找到当前用户信息。");
}
var userId = user.Id; // 假设当前用户是学生获取其ID
var result = await _submissionServices.GetStudentSubmissionSummariesAsync(userId);
if (result.Status)
{
return Ok(result);
}
else
{
return BadRequest(result.Message);
}
}
/// <summary>
/// 获取学生提交摘要。
/// </summary>
/// <param name="userId">用户ID。</param>
/// <returns>学生提交摘要列表或错误信息。</returns>
[HttpGet("getStudentSubmissionSummaries/{userId:guid}")]
[Authorize(Roles = "Teacher")]
public async Task<IActionResult> GetStudentSubmissionSummariesAsync(Guid userId)
{
var result = await _submissionServices.GetStudentSubmissionSummariesAsync(userId);
if (result.Status)
{
return Ok(result);
}
else
{
return BadRequest(result.Message);
}
}
/// <summary>
/// 获取学生提交详情。
/// </summary>
/// <param name="submissionId">提交ID。</param>
/// <returns>学生提交详情或错误信息。</returns>
[HttpGet("getStudentSubmissionDetail/{submissionId:guid}")]
public async Task<IActionResult> GetStudentSubmissionDetailAsync(Guid submissionId)
{
var result = await _submissionServices.GetStudentSubmissionDetailAsync(submissionId);
if (result.Status)
{
return Ok(result);
}
else
{
return BadRequest(result.Message);
}
}
}
}

View File

@@ -0,0 +1,223 @@
using Entities.Contracts;
using Entities.DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using TechHelper.Services;
using TechHelper.Services.Beta;
namespace TechHelper.Server.Controllers
{
[Route("api/submission-detail")]
[ApiController]
[Authorize]
public class SubmissionDetailController : ControllerBase
{
private readonly UserManager<User> _userManager;
private readonly ISubmissionDetailService _submissionDetailService;
public SubmissionDetailController(UserManager<User> userManager, ISubmissionDetailService submissionDetailService)
{
_userManager = userManager;
_submissionDetailService = submissionDetailService;
}
#region CRUD操作
/// <summary>
/// 获取所有提交详情
/// </summary>
/// <param name="query">查询参数</param>
/// <returns>提交详情列表</returns>
[HttpGet()]
[Authorize(Roles = "Admin,Teacher")]
public async Task<IActionResult> GetAllAsync([FromQuery] QueryParameter query)
{
var result = await _submissionDetailService.GetAllAsync(query);
return result.Status ? Ok(result) : BadRequest(result.Message);
}
/// <summary>
/// 根据ID获取提交详情
/// </summary>
/// <param name="id">提交详情ID</param>
/// <returns>提交详情详情</returns>
[HttpGet("{id:guid}")]
public async Task<IActionResult> GetAsync(Guid id)
{
var result = await _submissionDetailService.GetAsync(id);
return result.Status ? Ok(result) : BadRequest(result.Message);
}
/// <summary>
/// 创建提交详情
/// </summary>
/// <param name="model">提交详情数据传输对象</param>
/// <returns>创建结果</returns>
[HttpPost()]
public async Task<IActionResult> AddAsync([FromBody] SubmissionDetailDto model)
{
var result = await _submissionDetailService.AddAsync(model);
return result.Status ? StatusCode(201, result) : BadRequest(result.Message);
}
/// <summary>
/// 更新提交详情
/// </summary>
/// <param name="id">提交详情ID</param>
/// <param name="model">提交详情数据传输对象</param>
/// <returns>更新结果</returns>
[HttpPut("{id:guid}")]
public async Task<IActionResult> UpdateAsync(Guid id, [FromBody] SubmissionDetailDto model)
{
if (id != model.Id)
{
return BadRequest("路由ID与请求体中的ID不匹配。");
}
var result = await _submissionDetailService.UpdateAsync(model);
return result.Status ? Ok(result) : BadRequest(result.Message);
}
/// <summary>
/// 删除提交详情
/// </summary>
/// <param name="id">提交详情ID</param>
/// <returns>删除结果</returns>
[HttpDelete("delete/{id:guid}")]
public async Task<IActionResult> DeleteAsync(Guid id)
{
var result = await _submissionDetailService.DeleteAsync(id);
return result.Status ? NoContent() : BadRequest(result.Message);
}
#endregion
#region
/// <summary>
/// 根据提交ID获取提交详情列表
/// </summary>
/// <param name="submissionId">提交ID</param>
/// <returns>提交详情列表</returns>
[HttpGet("by-submission/{submissionId:guid}")]
public async Task<IActionResult> GetBySubmissionIdAsync(Guid submissionId)
{
var result = await _submissionDetailService.GetBySubmissionIdAsync(submissionId);
return result.Status ? Ok(result) : BadRequest(result.Message);
}
/// <summary>
/// 根据学生ID和考试ID获取提交详情
/// </summary>
/// <param name="studentId">学生ID</param>
/// <param name="examId">考试ID</param>
/// <returns>提交详情列表</returns>
[HttpGet("by-student-exam")]
public async Task<IActionResult> GetByStudentAndExamAsync([FromQuery] Guid studentId, [FromQuery] Guid examId)
{
var result = await _submissionDetailService.GetByStudentAndExamAsync(studentId, examId);
return result.Status ? Ok(result) : BadRequest(result.Message);
}
/// <summary>
/// 批量创建提交详情
/// </summary>
/// <param name="submissionId">提交ID</param>
/// <param name="details">提交详情列表</param>
/// <returns>创建结果</returns>
[HttpPost("batch-create/{submissionId:guid}")]
public async Task<IActionResult> BatchCreateAsync(Guid submissionId, [FromBody] List<SubmissionDetailDto> details)
{
var result = await _submissionDetailService.BatchCreateAsync(submissionId, details);
return result.Status ? StatusCode(201, result) : BadRequest(result.Message);
}
/// <summary>
/// 批量更新提交详情
/// </summary>
/// <param name="details">提交详情列表</param>
/// <returns>更新结果</returns>
[HttpPut("batch-update")]
public async Task<IActionResult> BatchUpdateAsync([FromBody] List<SubmissionDetailDto> details)
{
var result = await _submissionDetailService.BatchUpdateAsync(details);
return result.Status ? Ok(result) : BadRequest(result.Message);
}
/// <summary>
/// 更新提交详情评分
/// </summary>
/// <param name="detailId">提交详情ID</param>
/// <param name="points">分数</param>
/// <param name="feedback">反馈</param>
/// <returns>更新结果</returns>
[HttpPut("{detailId:guid}/score")]
public async Task<IActionResult> UpdateScoreAsync(Guid detailId, [FromQuery] float? points, [FromQuery] string? feedback)
{
var result = await _submissionDetailService.UpdateScoreAsync(detailId, points, feedback);
return result.Status ? Ok(result) : BadRequest(result.Message);
}
/// <summary>
/// 获取错题详情
/// </summary>
/// <param name="studentId">学生ID</param>
/// <param name="examId">考试ID</param>
/// <returns>错题详情列表</returns>
[HttpGet("error-details")]
[Authorize(Roles = "Student,Teacher")]
public async Task<IActionResult> GetErrorDetailsAsync([FromQuery] Guid studentId, [FromQuery] Guid examId)
{
var result = await _submissionDetailService.GetErrorDetailsAsync(studentId, examId);
return result.Status ? Ok(result) : BadRequest(result.Message);
}
/// <summary>
/// 获取正确题详情
/// </summary>
/// <param name="studentId">学生ID</param>
/// <param name="examId">考试ID</param>
/// <returns>正确题详情列表</returns>
[HttpGet("correct-details")]
[Authorize(Roles = "Student,Teacher")]
public async Task<IActionResult> GetCorrectDetailsAsync([FromQuery] Guid studentId, [FromQuery] Guid examId)
{
var result = await _submissionDetailService.GetCorrectDetailsAsync(studentId, examId);
return result.Status ? Ok(result) : BadRequest(result.Message);
}
/// <summary>
/// 获取未批改的提交详情
/// </summary>
/// <returns>未批改的提交详情列表</returns>
[HttpGet("ungraded")]
[Authorize(Roles = "Teacher")]
public async Task<IActionResult> GetUngradedDetailsAsync()
{
var user = await _userManager.FindByEmailAsync(User.Identity.Name);
if (user == null)
{
return NotFound("未找到当前用户信息。");
}
var result = await _submissionDetailService.GetUngradedDetailsAsync(user.Id);
return result.Status ? Ok(result) : BadRequest(result.Message);
}
/// <summary>
/// 批量更新提交详情状态
/// </summary>
/// <param name="submissionId">提交ID</param>
/// <param name="status">状态</param>
/// <returns>更新结果</returns>
[HttpPut("{submissionId:guid}/status")]
public async Task<IActionResult> UpdateStatusAsync(Guid submissionId, [FromQuery] SubmissionStatus status)
{
var result = await _submissionDetailService.UpdateStatusAsync(submissionId, status);
return result.Status ? Ok(result) : BadRequest(result.Message);
}
#endregion
}
}

View File

@@ -0,0 +1,209 @@
using Entities.Contracts;
using Entities.DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using TechHelper.Services;
using TechHelper.Services.Beta;
namespace TechHelper.Server.Controllers
{
/// <summary>
/// 教材管理控制器
/// 处理教材相关的操作,如创建、更新、删除教材等
/// </summary>
[Route("api/textbook")]
[ApiController]
public class TextbookController : ControllerBase
{
private readonly ITextbookService _textbookService;
private readonly UserManager<User> _userManager;
/// <summary>
/// 初始化教材控制器
/// </summary>
/// <param name="textbookService">教材服务</param>
/// <param name="userManager">用户管理服务</param>
public TextbookController(ITextbookService textbookService, UserManager<User> userManager)
{
_textbookService = textbookService;
_userManager = userManager;
}
#region CRUD操作
/// <summary>
/// 获取教材列表(支持搜索)
/// </summary>
/// <param name="query">查询参数</param>
/// <returns>教材列表</returns>
/// <response code="200">成功获取教材列表</response>
/// <response code="400">获取失败</response>
[HttpGet]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetAll([FromQuery] QueryParameter query)
{
var result = await _textbookService.GetAllAsync(query);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 根据ID获取教材详细信息
/// </summary>
/// <param name="id">教材ID</param>
/// <returns>教材详细信息</returns>
/// <response code="200">成功获取教材信息</response>
/// <response code="400">教材未找到或获取失败</response>
[HttpGet("{id}")]
[Authorize(Roles = "Teacher,Admin")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await _textbookService.GetAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 创建新教材
/// </summary>
/// <param name="model">教材数据传输对象</param>
/// <returns>创建结果</returns>
/// <response code="200">创建成功</response>
/// <response code="400">创建失败</response>
[HttpPost]
[Authorize(Roles = "Admin,Teacher")]
public async Task<IActionResult> Create([FromBody] TextbookDto model)
{
var result = await _textbookService.AddAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 更新教材信息
/// </summary>
/// <param name="model">教材数据传输对象</param>
/// <returns>更新结果</returns>
/// <response code="200">更新成功</response>
/// <response code="400">更新失败</response>
[HttpPut]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Update([FromBody] TextbookDto model)
{
var result = await _textbookService.UpdateAsync(model);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 删除教材
/// </summary>
/// <param name="id">教材ID</param>
/// <returns>删除结果</returns>
/// <response code="200">删除成功</response>
/// <response code="400">删除失败</response>
[HttpDelete("{id}")]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Delete(Guid id)
{
var result = await _textbookService.DeleteAsync(id);
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Message);
}
#endregion
#region
/// <summary>
/// 根据年级获取教材列表
/// </summary>
/// <param name="grade">年级</param>
/// <returns>教材列表</returns>
/// <response code="200">成功获取教材列表</response>
/// <response code="400">获取失败</response>
[HttpGet("grade/{grade}")]
[Authorize(Roles = "Student,Teacher,Admin")]
public async Task<IActionResult> GetByGrade(string grade)
{
var result = await _textbookService.GetAllAsync(new QueryParameter { Search = grade });
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 根据出版社获取教材列表
/// </summary>
/// <param name="publisher">出版社</param>
/// <returns>教材列表</returns>
/// <response code="200">成功获取教材列表</response>
/// <response code="400">获取失败</response>
[HttpGet("publisher/{publisher}")]
[Authorize(Roles = "Student,Teacher,Admin")]
public async Task<IActionResult> GetByPublisher(string publisher)
{
var result = await _textbookService.GetAllAsync(new QueryParameter { Search = publisher });
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
/// <summary>
/// 根据学科领域获取教材列表
/// </summary>
/// <param name="subjectArea">学科领域</param>
/// <returns>教材列表</returns>
/// <response code="200">成功获取教材列表</response>
/// <response code="400">获取失败</response>
[HttpGet("subjectArea/{subjectArea}")]
[Authorize(Roles = "Student,Teacher,Admin")]
public async Task<IActionResult> GetBySubjectArea(string subjectArea)
{
var result = await _textbookService.GetAllAsync(new QueryParameter { Search = subjectArea });
if (!result.Status)
{
return BadRequest(result.Message);
}
return Ok(result.Result);
}
#endregion
}
}

View File

@@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Entities.Contracts;
using TechHelper.Services.Beta;
namespace TechHelper.Controllers
{

View File

@@ -1,20 +1,23 @@
using Entities.Contracts;
using Entities.DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using TechHelper.Server.Services;
using TechHelper.Services;
using TechHelper.Services.Beta;
namespace TechHelper.Server.Controllers
{
[Route("api/user")]
[ApiController]
[Authorize]
public class UserController : ControllerBase
{
private IUserSerivces _userSerivces;
private IClassService _classService;
private UserManager<User> _userManager;
private readonly IUserSerivces _userSerivces;
private readonly IClassService _classService;
private readonly UserManager<User> _userManager;
public UserController(IClassService classService, UserManager<User> userManager, IUserSerivces userSerivces)
{
_classService = classService;
@@ -22,29 +25,186 @@ namespace TechHelper.Server.Controllers
_userSerivces = userSerivces;
}
[HttpPost("get")]
public async Task<IActionResult> GetAsync(
[FromBody] UserRegistrationToClassDto toClass)
/// <summary>
/// 获取指定用户信息
/// </summary>
/// <param name="id">用户ID</param>
/// <returns>用户信息</returns>
[HttpGet("{id}")]
public async Task<IActionResult> GetUserById(Guid id)
{
return Ok();
var result = await _userSerivces.GetAsync(id);
if (!result.Status)
{
return NotFound(result);
}
return Ok(result);
}
/// <summary>
/// 获取所有用户列表
/// </summary>
/// <param name="query">查询参数</param>
/// <returns>用户列表</returns>
[HttpGet]
public async Task<IActionResult> GetAllUsers([FromQuery] QueryParameter query)
{
var result = await _userSerivces.GetAllAsync(query);
if (!result.Status)
{
return BadRequest(result);
}
return Ok(result);
}
/// <summary>
/// 添加新用户
/// </summary>
/// <param name="userDto">用户数据</param>
/// <returns>操作结果</returns>
[HttpPost]
public async Task<IActionResult> AddUser([FromBody] UserDto userDto)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var result = await _userSerivces.AddAsync(userDto);
if (!result.Status)
{
return BadRequest(result);
}
return CreatedAtAction(nameof(GetUserById), new { id = userDto.Id }, result);
}
/// <summary>
/// 更新用户信息
/// </summary>
/// <param name="id">用户ID</param>
/// <param name="userDto">用户数据</param>
/// <returns>操作结果</returns>
[HttpPut("{id}")]
public async Task<IActionResult> UpdateUser(Guid id, [FromBody] UserDto userDto)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != userDto.Id)
{
return BadRequest("用户ID不匹配");
}
var result = await _userSerivces.UpdateAsync(userDto);
if (!result.Status)
{
return BadRequest(result);
}
return Ok(result);
}
/// <summary>
/// 删除用户
/// </summary>
/// <param name="id">用户ID</param>
/// <returns>操作结果</returns>
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteUser(Guid id)
{
var result = await _userSerivces.DeleteAsync(id);
if (!result.Status)
{
return BadRequest(result);
}
return Ok(result);
}
/// <summary>
/// 获取学生详细信息
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns>学生详细信息</returns>
[HttpGet("student/{userId}")]
public async Task<IActionResult> GetStudentDetailInfo(Guid userId)
{
var result = await _userSerivces.GetStudentDetailInfo(userId);
if (!result.Status)
{
return NotFound(result);
}
return Ok(result);
}
/// <summary>
/// 验证用户信息
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns>验证结果</returns>
[HttpPost("verify/{userId}")]
public async Task<IActionResult> VerifyUserInformation(Guid userId)
{
var result = await _userSerivces.VerifyUserInformation(userId);
if (!result.Status)
{
return BadRequest(result);
}
return Ok(result);
}
/// <summary>
/// 恢复用户角色信息
/// </summary>
/// <returns>操作结果</returns>
[HttpGet("restoreUserRole")]
public async Task<IActionResult> RestoreUserRole()
{
var user = await _userManager.FindByEmailAsync(User.Identity.Name);
if (user == null) return NotFound();
if (user == null) return NotFound("用户不存在");
if (User.IsInRole("Teacher") || User.IsInRole("Student"))
return Ok();
return Ok(new ApiResponse(true, "用户角色已正确设置"));
var result = await _userSerivces.RestoreUserRoleInformation(user);
if (result.Status)
return Ok();
return Ok(result);
else
return Unauthorized();
return Unauthorized(result);
}
/// <summary>
/// 注册新用户
/// </summary>
/// <param name="registrationDto">注册数据</param>
/// <returns>注册结果</returns>
[HttpPost("register")]
[AllowAnonymous]
public async Task<IActionResult> RegisterNewUser([FromBody] UserForRegistrationDto registrationDto)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var result = await _userSerivces.RegisterNewUserAsync(registrationDto);
if (!result.Status)
{
return BadRequest(result);
}
return Ok(result);
}
/// <summary>
/// 获取指定用户信息(旧接口)
/// </summary>
/// <param name="toClass">班级注册数据</param>
/// <returns>操作结果</returns>
[HttpPost("get")]
[Obsolete("请使用 GET /api/user/{id} 接口")]
public async Task<IActionResult> GetAsync([FromBody] UserRegistrationToClassDto toClass)
{
return Ok(new ApiResponse(false, "此接口已弃用,请使用新的接口"));
}
}
}

View File

@@ -1,33 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace TechHelper.Server.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,153 +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 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);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,71 +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 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" }
});
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,102 +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 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" }
});
}
}
}

View File

@@ -1,82 +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 _update_submisstion_detail : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
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.AddColumn<int>(
name: "status",
table: "submission_details",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("14b8854f-a38b-4e72-878e-31ba2f7528b2"), null, "Teacher", "TEACHER" },
{ new Guid("69c3cc0c-b284-433e-8493-9b1e7bd1eb1f"), null, "Student", "STUDENT" },
{ new Guid("6ef4d2bb-05da-4c17-9152-4467d86939fc"), null, "Administrator", "ADMINISTRATOR" }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("14b8854f-a38b-4e72-878e-31ba2f7528b2"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("69c3cc0c-b284-433e-8493-9b1e7bd1eb1f"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("6ef4d2bb-05da-4c17-9152-4467d86939fc"));
migrationBuilder.DropColumn(
name: "status",
table: "submission_details");
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" }
});
}
}
}

View File

@@ -1,89 +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 atemp_number_convert_to_byte : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("14b8854f-a38b-4e72-878e-31ba2f7528b2"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("69c3cc0c-b284-433e-8493-9b1e7bd1eb1f"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("6ef4d2bb-05da-4c17-9152-4467d86939fc"));
migrationBuilder.AlterColumn<byte>(
name: "attempt_number",
table: "submissions",
type: "tinyint unsigned",
nullable: false,
oldClrType: typeof(Guid),
oldType: "char(36)")
.OldAnnotation("Relational:Collation", "ascii_general_ci");
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("379143a2-8d7f-4ef7-b7c0-14701b710f87"), null, "Administrator", "ADMINISTRATOR" },
{ new Guid("6d49bb08-97d6-4a38-88a7-8080925b589b"), null, "Student", "STUDENT" },
{ new Guid("e330c745-f422-43e3-bcdf-1439ace3c52f"), null, "Teacher", "TEACHER" }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("379143a2-8d7f-4ef7-b7c0-14701b710f87"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("6d49bb08-97d6-4a38-88a7-8080925b589b"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("e330c745-f422-43e3-bcdf-1439ace3c52f"));
migrationBuilder.AlterColumn<Guid>(
name: "attempt_number",
table: "submissions",
type: "char(36)",
nullable: false,
collation: "ascii_general_ci",
oldClrType: typeof(byte),
oldType: "tinyint unsigned");
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("14b8854f-a38b-4e72-878e-31ba2f7528b2"), null, "Teacher", "TEACHER" },
{ new Guid("69c3cc0c-b284-433e-8493-9b1e7bd1eb1f"), null, "Student", "STUDENT" },
{ new Guid("6ef4d2bb-05da-4c17-9152-4467d86939fc"), null, "Administrator", "ADMINISTRATOR" }
});
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,104 +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 score_in_submission : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("379143a2-8d7f-4ef7-b7c0-14701b710f87"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("6d49bb08-97d6-4a38-88a7-8080925b589b"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("e330c745-f422-43e3-bcdf-1439ace3c52f"));
migrationBuilder.AddColumn<byte>(
name: "ErrorQuesNum",
table: "submissions",
type: "tinyint unsigned",
nullable: false,
defaultValue: (byte)0);
migrationBuilder.AddColumn<byte>(
name: "TotalQuesNum",
table: "submissions",
type: "tinyint unsigned",
nullable: false,
defaultValue: (byte)0);
migrationBuilder.AddColumn<byte>(
name: "TotalScore",
table: "submissions",
type: "tinyint unsigned",
nullable: false,
defaultValue: (byte)0);
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("53307917-63c4-468a-ab05-a03882a69ef8"), null, "Teacher", "TEACHER" },
{ new Guid("789b7819-685f-4a2b-9adf-463f397f24d1"), null, "Administrator", "ADMINISTRATOR" },
{ new Guid("bbea7915-e27c-4ddc-b06c-1f579fc8104e"), null, "Student", "STUDENT" }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("53307917-63c4-468a-ab05-a03882a69ef8"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("789b7819-685f-4a2b-9adf-463f397f24d1"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("bbea7915-e27c-4ddc-b06c-1f579fc8104e"));
migrationBuilder.DropColumn(
name: "ErrorQuesNum",
table: "submissions");
migrationBuilder.DropColumn(
name: "TotalQuesNum",
table: "submissions");
migrationBuilder.DropColumn(
name: "TotalScore",
table: "submissions");
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("379143a2-8d7f-4ef7-b7c0-14701b710f87"), null, "Administrator", "ADMINISTRATOR" },
{ new Guid("6d49bb08-97d6-4a38-88a7-8080925b589b"), null, "Student", "STUDENT" },
{ new Guid("e330c745-f422-43e3-bcdf-1439ace3c52f"), null, "Teacher", "TEACHER" }
});
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,93 +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_assign_data : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("53307917-63c4-468a-ab05-a03882a69ef8"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("789b7819-685f-4a2b-9adf-463f397f24d1"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("bbea7915-e27c-4ddc-b06c-1f579fc8104e"));
migrationBuilder.AddColumn<byte>(
name: "ExamType",
table: "assignments",
type: "tinyint unsigned",
nullable: false,
defaultValue: (byte)0);
migrationBuilder.AddColumn<string>(
name: "Name",
table: "assignments",
type: "longtext",
nullable: false)
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("0775702a-5db7-4747-94d0-4376fad2b58b"), null, "Teacher", "TEACHER" },
{ new Guid("37f41430-0cb7-44e5-988b-976200bd602d"), null, "Administrator", "ADMINISTRATOR" },
{ new Guid("df89b9a0-65ef-42dd-b2cb-e59997a72e70"), null, "Student", "STUDENT" }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("0775702a-5db7-4747-94d0-4376fad2b58b"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("37f41430-0cb7-44e5-988b-976200bd602d"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("df89b9a0-65ef-42dd-b2cb-e59997a72e70"));
migrationBuilder.DropColumn(
name: "ExamType",
table: "assignments");
migrationBuilder.DropColumn(
name: "Name",
table: "assignments");
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("53307917-63c4-468a-ab05-a03882a69ef8"), null, "Teacher", "TEACHER" },
{ new Guid("789b7819-685f-4a2b-9adf-463f397f24d1"), null, "Administrator", "ADMINISTRATOR" },
{ new Guid("bbea7915-e27c-4ddc-b06c-1f579fc8104e"), null, "Student", "STUDENT" }
});
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,93 +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 question_qt_update : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("0775702a-5db7-4747-94d0-4376fad2b58b"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("37f41430-0cb7-44e5-988b-976200bd602d"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("df89b9a0-65ef-42dd-b2cb-e59997a72e70"));
migrationBuilder.AddColumn<string>(
name: "QType",
table: "questions",
type: "longtext",
nullable: false)
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.AddColumn<byte>(
name: "Type",
table: "assignment_questions",
type: "tinyint unsigned",
nullable: false,
defaultValue: (byte)0);
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("67de6514-79a5-4a9c-b54c-13cac296b0c6"), null, "Teacher", "TEACHER" },
{ new Guid("94f0d8d9-ffba-4e28-b578-8596363d42ae"), null, "Student", "STUDENT" },
{ new Guid("bf46ed67-2dc9-40f8-8717-37dd3572f274"), null, "Administrator", "ADMINISTRATOR" }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("67de6514-79a5-4a9c-b54c-13cac296b0c6"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("94f0d8d9-ffba-4e28-b578-8596363d42ae"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("bf46ed67-2dc9-40f8-8717-37dd3572f274"));
migrationBuilder.DropColumn(
name: "QType",
table: "questions");
migrationBuilder.DropColumn(
name: "Type",
table: "assignment_questions");
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("0775702a-5db7-4747-94d0-4376fad2b58b"), null, "Teacher", "TEACHER" },
{ new Guid("37f41430-0cb7-44e5-988b-976200bd602d"), null, "Administrator", "ADMINISTRATOR" },
{ new Guid("df89b9a0-65ef-42dd-b2cb-e59997a72e70"), null, "Student", "STUDENT" }
});
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,89 +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 question_qt_update_2 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("67de6514-79a5-4a9c-b54c-13cac296b0c6"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("94f0d8d9-ffba-4e28-b578-8596363d42ae"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("bf46ed67-2dc9-40f8-8717-37dd3572f274"));
migrationBuilder.CreateTable(
name: "global",
columns: table => new
{
id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Area = table.Column<byte>(type: "tinyint unsigned", nullable: false),
Info = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_global", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("49854839-b861-4d42-bdbe-96b1a66c25ef"), null, "Teacher", "TEACHER" },
{ new Guid("5c7a7971-2610-4bce-9e41-0caffd5a5558"), null, "Student", "STUDENT" },
{ new Guid("83ff7de8-edc9-47f8-8de8-22f892ca6bb5"), null, "Administrator", "ADMINISTRATOR" }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "global");
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("49854839-b861-4d42-bdbe-96b1a66c25ef"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("5c7a7971-2610-4bce-9e41-0caffd5a5558"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("83ff7de8-edc9-47f8-8de8-22f892ca6bb5"));
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("67de6514-79a5-4a9c-b54c-13cac296b0c6"), null, "Teacher", "TEACHER" },
{ new Guid("94f0d8d9-ffba-4e28-b578-8596363d42ae"), null, "Student", "STUDENT" },
{ new Guid("bf46ed67-2dc9-40f8-8717-37dd3572f274"), null, "Administrator", "ADMINISTRATOR" }
});
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,82 +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 question_qt_update_3 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("49854839-b861-4d42-bdbe-96b1a66c25ef"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("5c7a7971-2610-4bce-9e41-0caffd5a5558"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("83ff7de8-edc9-47f8-8de8-22f892ca6bb5"));
migrationBuilder.AddColumn<byte>(
name: "SubjectArea",
table: "AspNetUsers",
type: "tinyint unsigned",
nullable: false,
defaultValue: (byte)0);
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("2670f35a-df0c-4071-8879-80eb99d138a1"), null, "Teacher", "TEACHER" },
{ new Guid("8c6c5e8e-ef00-444c-9c7c-cba5cd6f7043"), null, "Student", "STUDENT" },
{ new Guid("9eda9d90-0cd2-4fbe-b07e-f90bd01f32db"), null, "Administrator", "ADMINISTRATOR" }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("2670f35a-df0c-4071-8879-80eb99d138a1"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("8c6c5e8e-ef00-444c-9c7c-cba5cd6f7043"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("9eda9d90-0cd2-4fbe-b07e-f90bd01f32db"));
migrationBuilder.DropColumn(
name: "SubjectArea",
table: "AspNetUsers");
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("49854839-b861-4d42-bdbe-96b1a66c25ef"), null, "Teacher", "TEACHER" },
{ new Guid("5c7a7971-2610-4bce-9e41-0caffd5a5558"), null, "Student", "STUDENT" },
{ new Guid("83ff7de8-edc9-47f8-8de8-22f892ca6bb5"), null, "Administrator", "ADMINISTRATOR" }
});
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,97 +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 submission_up_2 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("2670f35a-df0c-4071-8879-80eb99d138a1"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("8c6c5e8e-ef00-444c-9c7c-cba5cd6f7043"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("9eda9d90-0cd2-4fbe-b07e-f90bd01f32db"));
migrationBuilder.AlterColumn<float>(
name: "overall_grade",
table: "submissions",
type: "float",
precision: 5,
scale: 2,
nullable: false,
defaultValue: 0f,
oldClrType: typeof(float),
oldType: "float",
oldPrecision: 5,
oldScale: 2,
oldNullable: true);
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("264e4290-9d15-478d-8c49-8d0935e5a6e1"), null, "Administrator", "ADMINISTRATOR" },
{ new Guid("73cafcee-3e99-43ae-86c5-c01a1cbc6124"), null, "Teacher", "TEACHER" },
{ new Guid("f06927ff-4bba-4ab6-8f0a-e45a765c2fcc"), null, "Student", "STUDENT" }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("264e4290-9d15-478d-8c49-8d0935e5a6e1"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("73cafcee-3e99-43ae-86c5-c01a1cbc6124"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("f06927ff-4bba-4ab6-8f0a-e45a765c2fcc"));
migrationBuilder.AlterColumn<float>(
name: "overall_grade",
table: "submissions",
type: "float",
precision: 5,
scale: 2,
nullable: true,
oldClrType: typeof(float),
oldType: "float",
oldPrecision: 5,
oldScale: 2);
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("2670f35a-df0c-4071-8879-80eb99d138a1"), null, "Teacher", "TEACHER" },
{ new Guid("8c6c5e8e-ef00-444c-9c7c-cba5cd6f7043"), null, "Student", "STUDENT" },
{ new Guid("9eda9d90-0cd2-4fbe-b07e-f90bd01f32db"), null, "Administrator", "ADMINISTRATOR" }
});
}
}
}

View File

@@ -1,71 +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 submission_up_3 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("264e4290-9d15-478d-8c49-8d0935e5a6e1"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("73cafcee-3e99-43ae-86c5-c01a1cbc6124"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("f06927ff-4bba-4ab6-8f0a-e45a765c2fcc"));
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("388fdb1d-8cd5-4e8f-b49c-06dbee60527b"), null, "Administrator", "ADMINISTRATOR" },
{ new Guid("ba4054d5-2f8a-4c7f-bd56-0fc864720c7d"), null, "Teacher", "TEACHER" },
{ new Guid("c758a0d2-faea-4cf1-aa14-d162f3d0a1e9"), null, "Student", "STUDENT" }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("388fdb1d-8cd5-4e8f-b49c-06dbee60527b"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("ba4054d5-2f8a-4c7f-bd56-0fc864720c7d"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("c758a0d2-faea-4cf1-aa14-d162f3d0a1e9"));
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("264e4290-9d15-478d-8c49-8d0935e5a6e1"), null, "Administrator", "ADMINISTRATOR" },
{ new Guid("73cafcee-3e99-43ae-86c5-c01a1cbc6124"), null, "Teacher", "TEACHER" },
{ new Guid("f06927ff-4bba-4ab6-8f0a-e45a765c2fcc"), null, "Student", "STUDENT" }
});
}
}
}

View File

@@ -1,82 +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 tee : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("388fdb1d-8cd5-4e8f-b49c-06dbee60527b"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("ba4054d5-2f8a-4c7f-bd56-0fc864720c7d"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("c758a0d2-faea-4cf1-aa14-d162f3d0a1e9"));
migrationBuilder.AddColumn<bool>(
name: "BCorrect",
table: "assignment_questions",
type: "tinyint(1)",
nullable: false,
defaultValue: false);
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("d480cdca-7de2-4abe-8129-73bbaa6c1b32"), null, "Student", "STUDENT" },
{ new Guid("d7bcfb37-3f1c-467b-a3f0-b2339a8a990d"), null, "Teacher", "TEACHER" },
{ new Guid("f4a6788a-04d8-499c-9e64-73dfba97ca6b"), null, "Administrator", "ADMINISTRATOR" }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("d480cdca-7de2-4abe-8129-73bbaa6c1b32"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("d7bcfb37-3f1c-467b-a3f0-b2339a8a990d"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("f4a6788a-04d8-499c-9e64-73dfba97ca6b"));
migrationBuilder.DropColumn(
name: "BCorrect",
table: "assignment_questions");
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("388fdb1d-8cd5-4e8f-b49c-06dbee60527b"), null, "Administrator", "ADMINISTRATOR" },
{ new Guid("ba4054d5-2f8a-4c7f-bd56-0fc864720c7d"), null, "Teacher", "TEACHER" },
{ new Guid("c758a0d2-faea-4cf1-aa14-d162f3d0a1e9"), null, "Student", "STUDENT" }
});
}
}
}

View File

@@ -4,8 +4,6 @@ using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace TechHelper.Server.Migrations
{
/// <inheritdoc />
@@ -36,44 +34,18 @@ namespace TechHelper.Server.Migrations
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "AspNetUsers",
name: "exam_type",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
RefreshToken = table.Column<string>(type: "longtext", nullable: true)
id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
name = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
RefreshTokenExpiryTime = table.Column<DateTime>(type: "datetime(6)", nullable: true),
Address = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
DisplayName = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false),
UserName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
NormalizedUserName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Email = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
NormalizedEmail = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
EmailConfirmed = table.Column<bool>(type: "tinyint(1)", nullable: false),
PasswordHash = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
SecurityStamp = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ConcurrencyStamp = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
PhoneNumber = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
PhoneNumberConfirmed = table.Column<bool>(type: "tinyint(1)", nullable: false),
TwoFactorEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: true),
LockoutEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
AccessFailedCount = table.Column<int>(type: "int", nullable: false)
description = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
table.PrimaryKey("PK_exam_type", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
@@ -91,6 +63,39 @@ namespace TechHelper.Server.Migrations
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "schools",
columns: table => new
{
id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
school_name = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
address = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
create_time = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_schools", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "subjects",
columns: table => new
{
id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
name = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
description = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_subjects", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "textbook",
columns: table => new
@@ -132,6 +137,125 @@ namespace TechHelper.Server.Migrations
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "grades",
columns: table => new
{
grade_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
school_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
grade_name = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
grade_level = table.Column<byte>(type: "tinyint unsigned", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_grades", x => x.grade_id);
table.ForeignKey(
name: "FK_grades_schools_school_id",
column: x => x.school_id,
principalTable: "schools",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "AspNetUsers",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
RefreshToken = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
RefreshTokenExpiryTime = table.Column<DateTime>(type: "datetime(6)", nullable: true),
HomeAddress = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
DisplayName = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Role = table.Column<int>(type: "int", nullable: true),
TeachSubjectId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false),
UserName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
NormalizedUserName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Email = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
NormalizedEmail = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
EmailConfirmed = table.Column<bool>(type: "tinyint(1)", nullable: false),
PasswordHash = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
SecurityStamp = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ConcurrencyStamp = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
PhoneNumber = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
PhoneNumberConfirmed = table.Column<bool>(type: "tinyint(1)", nullable: false),
TwoFactorEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: true),
LockoutEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
AccessFailedCount = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
table.ForeignKey(
name: "FK_AspNetUsers_subjects_TeachSubjectId",
column: x => x.TeachSubjectId,
principalTable: "subjects",
principalColumn: "id");
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "question_types",
columns: table => new
{
id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
name = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
subject_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
description = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
score_rule = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_question_types", x => x.id);
table.ForeignKey(
name: "FK_question_types_subjects_subject_id",
column: x => x.subject_id,
principalTable: "subjects",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "lesson",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Title = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Description = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
TextbookID = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_lesson", x => x.Id);
table.ForeignKey(
name: "FK_lesson_textbook_TextbookID",
column: x => x.TextbookID,
principalTable: "textbook",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "AspNetUserClaims",
columns: table => new
@@ -233,102 +357,29 @@ namespace TechHelper.Server.Migrations
name: "classes",
columns: table => new
{
id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
grade = table.Column<byte>(type: "tinyint unsigned", nullable: false),
@class = table.Column<byte>(name: "class", type: "tinyint unsigned", nullable: false),
description = table.Column<string>(type: "longtext", nullable: true)
class_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
grade_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
index = table.Column<byte>(type: "tinyint unsigned", nullable: false),
class_name = table.Column<string>(type: "varchar(30)", maxLength: 30, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
head_teacher_id = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
created_at = table.Column<DateTime>(type: "datetime(6)", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
updated_at = table.Column<DateTime>(type: "datetime(6)", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.ComputedColumn),
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValue: false)
created_at = table.Column<DateTime>(type: "datetime(6)", nullable: false),
updated_at = table.Column<DateTime>(type: "datetime(6)", nullable: false),
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_classes", x => x.id);
table.PrimaryKey("PK_classes", x => x.class_id);
table.ForeignKey(
name: "FK_classes_AspNetUsers_head_teacher_id",
column: x => x.head_teacher_id,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "lesson",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Title = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Description = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
TextbookID = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_lesson", x => x.Id);
principalColumn: "Id");
table.ForeignKey(
name: "FK_lesson_textbook_TextbookID",
column: x => x.TextbookID,
principalTable: "textbook",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "class_student",
columns: table => new
{
class_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"),
enrollment_date = table.Column<DateTime>(type: "datetime(6)", nullable: false),
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValue: false)
},
constraints: table =>
{
table.PrimaryKey("PK_class_student", x => new { x.class_id, x.student_id });
table.ForeignKey(
name: "FK_class_student_AspNetUsers_student_id",
column: x => x.student_id,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_class_student_classes_class_id",
column: x => x.class_id,
principalTable: "classes",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "class_teachers",
columns: table => new
{
class_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
teacher_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
subject_taught = table.Column<byte>(type: "tinyint unsigned", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_class_teachers", x => new { x.class_id, x.teacher_id });
table.ForeignKey(
name: "FK_class_teachers_AspNetUsers_teacher_id",
column: x => x.teacher_id,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_class_teachers_classes_class_id",
column: x => x.class_id,
principalTable: "classes",
principalColumn: "id",
name: "FK_classes_grades_grade_id",
column: x => x.grade_id,
principalTable: "grades",
principalColumn: "grade_id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
@@ -375,49 +426,77 @@ namespace TechHelper.Server.Migrations
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "class_user",
columns: table => new
{
class_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"),
enrollment_date = table.Column<DateTime>(type: "datetime(6)", nullable: false),
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_class_user", x => new { x.class_id, x.student_id });
table.ForeignKey(
name: "FK_class_user_AspNetUsers_student_id",
column: x => x.student_id,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_class_user_classes_class_id",
column: x => x.class_id,
principalTable: "classes",
principalColumn: "class_id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "questions",
columns: table => new
{
id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
question_text = table.Column<string>(type: "longtext", maxLength: 65535, nullable: false)
title = table.Column<string>(type: "longtext", maxLength: 65535, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
correct_answer = table.Column<string>(type: "longtext", maxLength: 65535, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
question_type = table.Column<byte>(type: "tinyint unsigned", maxLength: 20, nullable: false),
difficulty_level = table.Column<byte>(type: "tinyint unsigned", maxLength: 10, nullable: false),
subject_area = table.Column<byte>(type: "tinyint unsigned", maxLength: 100, nullable: false),
options = table.Column<string>(type: "longtext", nullable: true)
answer = table.Column<string>(type: "longtext", maxLength: 65535, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
type = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
subject_area = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
key_point = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
lesson = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
created_by = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
created_at = table.Column<DateTime>(type: "datetime(6)", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
updated_at = table.Column<DateTime>(type: "datetime(6)", rowVersion: true, nullable: false),
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValue: false)
options = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
created_at = table.Column<DateTime>(type: "datetime(6)", nullable: false),
updated_at = table.Column<DateTime>(type: "datetime(6)", nullable: false),
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_questions", x => x.id);
table.ForeignKey(
name: "FK_questions_AspNetUsers_created_by",
column: x => x.created_by,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_questions_key_point_key_point",
column: x => x.key_point,
principalTable: "key_point",
principalColumn: "Id",
onDelete: ReferentialAction.SetNull);
principalColumn: "Id");
table.ForeignKey(
name: "FK_questions_lesson_lesson",
column: x => x.lesson,
principalTable: "lesson",
principalColumn: "Id",
onDelete: ReferentialAction.SetNull);
principalColumn: "Id");
table.ForeignKey(
name: "FK_questions_question_types_type",
column: x => x.type,
principalTable: "question_types",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_questions_subjects_subject_area",
column: x => x.subject_area,
principalTable: "subjects",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
@@ -426,16 +505,18 @@ namespace TechHelper.Server.Migrations
columns: table => new
{
id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
question_id = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
title = table.Column<string>(type: "varchar(1024)", maxLength: 1024, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
question_id = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
description = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
question_number = table.Column<byte>(type: "tinyint unsigned", nullable: false),
sequence = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
parent_question_group_id = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
group_state = table.Column<byte>(type: "tinyint unsigned", nullable: false),
QuestionTypeId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
created_at = table.Column<DateTime>(type: "datetime(6)", nullable: false),
score = table.Column<float>(type: "float", nullable: true),
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValue: false)
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false)
},
constraints: table =>
{
@@ -444,19 +525,23 @@ namespace TechHelper.Server.Migrations
name: "FK_assignment_questions_QuestionContexts_description",
column: x => x.description,
principalTable: "QuestionContexts",
principalColumn: "Id",
onDelete: ReferentialAction.SetNull);
principalColumn: "Id");
table.ForeignKey(
name: "FK_assignment_questions_assignment_questions_parent_question_gr~",
column: x => x.parent_question_group_id,
principalTable: "assignment_questions",
principalColumn: "id");
table.ForeignKey(
name: "FK_assignment_questions_question_types_QuestionTypeId",
column: x => x.QuestionTypeId,
principalTable: "question_types",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_assignment_questions_questions_question_id",
column: x => x.question_id,
principalTable: "questions",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
principalColumn: "id");
})
.Annotation("MySql:CharSet", "utf8mb4");
@@ -469,25 +554,22 @@ namespace TechHelper.Server.Migrations
.Annotation("MySql:CharSet", "utf8mb4"),
description = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
subject_area = table.Column<byte>(type: "tinyint unsigned", nullable: false),
subject_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
exam_struct_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
exam_type_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
created_by = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
due_date = table.Column<DateTime>(type: "datetime(6)", nullable: false),
total_points = table.Column<byte>(type: "tinyint unsigned", nullable: false),
score = table.Column<float>(type: "float", nullable: false),
created_by = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
name = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
created_at = table.Column<DateTime>(type: "datetime(6)", nullable: false),
updated_at = table.Column<DateTime>(type: "datetime(6)", nullable: false),
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false),
UserId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci")
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_assignments", x => x.id);
table.ForeignKey(
name: "FK_assignments_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id");
table.ForeignKey(
name: "FK_assignments_AspNetUsers_created_by",
column: x => x.created_by,
@@ -500,6 +582,18 @@ namespace TechHelper.Server.Migrations
principalTable: "assignment_questions",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_assignments_exam_type_exam_type_id",
column: x => x.exam_type_id,
principalTable: "exam_type",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_assignments_subjects_subject_id",
column: x => x.subject_id,
principalTable: "subjects",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
@@ -528,49 +622,26 @@ namespace TechHelper.Server.Migrations
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "assignment_class",
columns: table => new
{
assignment_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
class_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
assigned_at = table.Column<DateTime>(type: "datetime(6)", nullable: false),
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValue: false)
},
constraints: table =>
{
table.PrimaryKey("PK_assignment_class", x => new { x.assignment_id, x.class_id });
table.ForeignKey(
name: "FK_assignment_class_assignments_assignment_id",
column: x => x.assignment_id,
principalTable: "assignments",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_assignment_class_classes_class_id",
column: x => x.class_id,
principalTable: "classes",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "submissions",
columns: table => new
{
id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
assignment_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
exam_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"),
attempt_number = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
graded_by = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
class_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
attempt_number = table.Column<byte>(type: "tinyint unsigned", 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", nullable: false),
overall_feedback = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
graded_by = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
graded_at = table.Column<DateTime>(type: "datetime(6)", nullable: true),
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValue: false),
status = table.Column<int>(type: "int", maxLength: 15, nullable: false)
TotalQuesNum = table.Column<byte>(type: "tinyint unsigned", nullable: false),
ErrorQuesNum = table.Column<byte>(type: "tinyint unsigned", nullable: false),
TotalScore = table.Column<byte>(type: "tinyint unsigned", nullable: false),
status = table.Column<int>(type: "int", nullable: false),
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false)
},
constraints: table =>
{
@@ -579,20 +650,25 @@ namespace TechHelper.Server.Migrations
name: "FK_submissions_AspNetUsers_graded_by",
column: x => x.graded_by,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.SetNull);
principalColumn: "Id");
table.ForeignKey(
name: "FK_submissions_AspNetUsers_student_id",
column: x => x.student_id,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_submissions_assignments_assignment_id",
column: x => x.assignment_id,
name: "FK_submissions_assignments_exam_id",
column: x => x.exam_id,
principalTable: "assignments",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_submissions_classes_class_id",
column: x => x.class_id,
principalTable: "classes",
principalColumn: "class_id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
@@ -607,13 +683,12 @@ namespace TechHelper.Server.Migrations
student_answer = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
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", nullable: true),
teacher_feedback = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
created_at = table.Column<DateTime>(type: "datetime(6)", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
updated_at = table.Column<DateTime>(type: "datetime(6)", rowVersion: true, nullable: false),
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValue: false)
created_at = table.Column<DateTime>(type: "datetime(6)", nullable: false),
updated_at = table.Column<DateTime>(type: "datetime(6)", nullable: false),
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false)
},
constraints: table =>
{
@@ -623,7 +698,7 @@ namespace TechHelper.Server.Migrations
column: x => x.student_id,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_submission_details_assignment_questions_assignment_question_~",
column: x => x.assignment_question_id,
@@ -639,16 +714,6 @@ namespace TechHelper.Server.Migrations
})
.Annotation("MySql:CharSet", "utf8mb4");
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.CreateIndex(
name: "IX_AspNetRoleClaims_RoleId",
table: "AspNetRoleClaims",
@@ -680,6 +745,11 @@ namespace TechHelper.Server.Migrations
table: "AspNetUsers",
column: "NormalizedEmail");
migrationBuilder.CreateIndex(
name: "IX_AspNetUsers_TeachSubjectId",
table: "AspNetUsers",
column: "TeachSubjectId");
migrationBuilder.CreateIndex(
name: "UserNameIndex",
table: "AspNetUsers",
@@ -691,11 +761,6 @@ namespace TechHelper.Server.Migrations
table: "assignment_attachments",
column: "assignment_id");
migrationBuilder.CreateIndex(
name: "IX_assignment_class_class_id",
table: "assignment_class",
column: "class_id");
migrationBuilder.CreateIndex(
name: "IX_assignment_questions_description",
table: "assignment_questions",
@@ -711,6 +776,11 @@ namespace TechHelper.Server.Migrations
table: "assignment_questions",
column: "question_id");
migrationBuilder.CreateIndex(
name: "IX_assignment_questions_QuestionTypeId",
table: "assignment_questions",
column: "QuestionTypeId");
migrationBuilder.CreateIndex(
name: "IX_assignments_created_by",
table: "assignments",
@@ -723,25 +793,35 @@ namespace TechHelper.Server.Migrations
unique: true);
migrationBuilder.CreateIndex(
name: "IX_assignments_UserId",
name: "IX_assignments_exam_type_id",
table: "assignments",
column: "UserId");
column: "exam_type_id");
migrationBuilder.CreateIndex(
name: "IX_class_student_student_id",
table: "class_student",
name: "IX_assignments_subject_id",
table: "assignments",
column: "subject_id");
migrationBuilder.CreateIndex(
name: "IX_class_user_student_id",
table: "class_user",
column: "student_id");
migrationBuilder.CreateIndex(
name: "IX_class_teachers_teacher_id",
table: "class_teachers",
column: "teacher_id");
name: "IX_classes_grade_id",
table: "classes",
column: "grade_id");
migrationBuilder.CreateIndex(
name: "IX_classes_head_teacher_id",
table: "classes",
column: "head_teacher_id");
migrationBuilder.CreateIndex(
name: "IX_grades_school_id",
table: "grades",
column: "school_id");
migrationBuilder.CreateIndex(
name: "IX_key_point_LessonID",
table: "key_point",
@@ -758,9 +838,9 @@ namespace TechHelper.Server.Migrations
column: "LessonID");
migrationBuilder.CreateIndex(
name: "IX_questions_created_by",
table: "questions",
column: "created_by");
name: "IX_question_types_subject_id",
table: "question_types",
column: "subject_id");
migrationBuilder.CreateIndex(
name: "IX_questions_key_point",
@@ -773,10 +853,14 @@ namespace TechHelper.Server.Migrations
column: "lesson");
migrationBuilder.CreateIndex(
name: "IX_questions_question_text",
name: "IX_questions_subject_area",
table: "questions",
column: "question_text")
.Annotation("MySql:IndexPrefixLength", new[] { 20 });
column: "subject_area");
migrationBuilder.CreateIndex(
name: "IX_questions_type",
table: "questions",
column: "type");
migrationBuilder.CreateIndex(
name: "IX_submission_details_assignment_question_id",
@@ -794,9 +878,14 @@ namespace TechHelper.Server.Migrations
column: "submission_id");
migrationBuilder.CreateIndex(
name: "IX_submissions_assignment_id",
name: "IX_submissions_class_id",
table: "submissions",
column: "assignment_id");
column: "class_id");
migrationBuilder.CreateIndex(
name: "IX_submissions_exam_id",
table: "submissions",
column: "exam_id");
migrationBuilder.CreateIndex(
name: "IX_submissions_graded_by",
@@ -831,13 +920,7 @@ namespace TechHelper.Server.Migrations
name: "assignment_attachments");
migrationBuilder.DropTable(
name: "assignment_class");
migrationBuilder.DropTable(
name: "class_student");
migrationBuilder.DropTable(
name: "class_teachers");
name: "class_user");
migrationBuilder.DropTable(
name: "lesson_question");
@@ -848,18 +931,27 @@ namespace TechHelper.Server.Migrations
migrationBuilder.DropTable(
name: "AspNetRoles");
migrationBuilder.DropTable(
name: "classes");
migrationBuilder.DropTable(
name: "submissions");
migrationBuilder.DropTable(
name: "assignments");
migrationBuilder.DropTable(
name: "classes");
migrationBuilder.DropTable(
name: "assignment_questions");
migrationBuilder.DropTable(
name: "exam_type");
migrationBuilder.DropTable(
name: "AspNetUsers");
migrationBuilder.DropTable(
name: "grades");
migrationBuilder.DropTable(
name: "QuestionContexts");
@@ -867,14 +959,20 @@ namespace TechHelper.Server.Migrations
name: "questions");
migrationBuilder.DropTable(
name: "AspNetUsers");
name: "schools");
migrationBuilder.DropTable(
name: "key_point");
migrationBuilder.DropTable(
name: "question_types");
migrationBuilder.DropTable(
name: "lesson");
migrationBuilder.DropTable(
name: "subjects");
migrationBuilder.DropTable(
name: "textbook");
}

View File

@@ -0,0 +1,501 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace TechHelper.Server.Migrations
{
/// <inheritdoc />
public partial class temp_1 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_assignment_attachments_assignments_assignment_id",
table: "assignment_attachments");
migrationBuilder.DropForeignKey(
name: "FK_assignment_questions_QuestionContexts_description",
table: "assignment_questions");
migrationBuilder.DropForeignKey(
name: "FK_assignment_questions_assignment_questions_parent_question_gr~",
table: "assignment_questions");
migrationBuilder.DropForeignKey(
name: "FK_assignment_questions_question_types_QuestionTypeId",
table: "assignment_questions");
migrationBuilder.DropForeignKey(
name: "FK_assignment_questions_questions_question_id",
table: "assignment_questions");
migrationBuilder.DropForeignKey(
name: "FK_assignments_AspNetUsers_created_by",
table: "assignments");
migrationBuilder.DropForeignKey(
name: "FK_assignments_assignment_questions_exam_struct_id",
table: "assignments");
migrationBuilder.DropForeignKey(
name: "FK_assignments_exam_type_exam_type_id",
table: "assignments");
migrationBuilder.DropForeignKey(
name: "FK_assignments_subjects_subject_id",
table: "assignments");
migrationBuilder.DropForeignKey(
name: "FK_submission_details_assignment_questions_assignment_question_~",
table: "submission_details");
migrationBuilder.DropForeignKey(
name: "FK_submissions_assignments_exam_id",
table: "submissions");
migrationBuilder.DropPrimaryKey(
name: "PK_assignments",
table: "assignments");
migrationBuilder.DropPrimaryKey(
name: "PK_assignment_questions",
table: "assignment_questions");
migrationBuilder.DropPrimaryKey(
name: "PK_assignment_attachments",
table: "assignment_attachments");
migrationBuilder.RenameTable(
name: "assignments",
newName: "exams");
migrationBuilder.RenameTable(
name: "assignment_questions",
newName: "exam_questions");
migrationBuilder.RenameTable(
name: "assignment_attachments",
newName: "exam_attachments");
migrationBuilder.RenameColumn(
name: "assignment_question_id",
table: "submission_details",
newName: "exam_question_id");
migrationBuilder.RenameIndex(
name: "IX_submission_details_assignment_question_id",
table: "submission_details",
newName: "IX_submission_details_exam_question_id");
migrationBuilder.RenameIndex(
name: "IX_assignments_subject_id",
table: "exams",
newName: "IX_exams_subject_id");
migrationBuilder.RenameIndex(
name: "IX_assignments_exam_type_id",
table: "exams",
newName: "IX_exams_exam_type_id");
migrationBuilder.RenameIndex(
name: "IX_assignments_exam_struct_id",
table: "exams",
newName: "IX_exams_exam_struct_id");
migrationBuilder.RenameIndex(
name: "IX_assignments_created_by",
table: "exams",
newName: "IX_exams_created_by");
migrationBuilder.RenameIndex(
name: "IX_assignment_questions_QuestionTypeId",
table: "exam_questions",
newName: "IX_exam_questions_QuestionTypeId");
migrationBuilder.RenameIndex(
name: "IX_assignment_questions_question_id",
table: "exam_questions",
newName: "IX_exam_questions_question_id");
migrationBuilder.RenameIndex(
name: "IX_assignment_questions_parent_question_group_id",
table: "exam_questions",
newName: "IX_exam_questions_parent_question_group_id");
migrationBuilder.RenameIndex(
name: "IX_assignment_questions_description",
table: "exam_questions",
newName: "IX_exam_questions_description");
migrationBuilder.RenameColumn(
name: "assignment_id",
table: "exam_attachments",
newName: "exam_id");
migrationBuilder.RenameIndex(
name: "IX_assignment_attachments_assignment_id",
table: "exam_attachments",
newName: "IX_exam_attachments_exam_id");
migrationBuilder.AlterColumn<float>(
name: "TotalScore",
table: "submissions",
type: "float",
nullable: false,
oldClrType: typeof(byte),
oldType: "tinyint unsigned");
migrationBuilder.AddColumn<byte>(
name: "exam_struct_type",
table: "exam_questions",
type: "tinyint unsigned",
nullable: false,
defaultValue: (byte)0);
migrationBuilder.AddPrimaryKey(
name: "PK_exams",
table: "exams",
column: "id");
migrationBuilder.AddPrimaryKey(
name: "PK_exam_questions",
table: "exam_questions",
column: "id");
migrationBuilder.AddPrimaryKey(
name: "PK_exam_attachments",
table: "exam_attachments",
column: "id");
migrationBuilder.AddForeignKey(
name: "FK_exam_attachments_exams_exam_id",
table: "exam_attachments",
column: "exam_id",
principalTable: "exams",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_exam_questions_QuestionContexts_description",
table: "exam_questions",
column: "description",
principalTable: "QuestionContexts",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_exam_questions_exam_questions_parent_question_group_id",
table: "exam_questions",
column: "parent_question_group_id",
principalTable: "exam_questions",
principalColumn: "id");
migrationBuilder.AddForeignKey(
name: "FK_exam_questions_question_types_QuestionTypeId",
table: "exam_questions",
column: "QuestionTypeId",
principalTable: "question_types",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_exam_questions_questions_question_id",
table: "exam_questions",
column: "question_id",
principalTable: "questions",
principalColumn: "id");
migrationBuilder.AddForeignKey(
name: "FK_exams_AspNetUsers_created_by",
table: "exams",
column: "created_by",
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_exams_exam_questions_exam_struct_id",
table: "exams",
column: "exam_struct_id",
principalTable: "exam_questions",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_exams_exam_type_exam_type_id",
table: "exams",
column: "exam_type_id",
principalTable: "exam_type",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_exams_subjects_subject_id",
table: "exams",
column: "subject_id",
principalTable: "subjects",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_submission_details_exam_questions_exam_question_id",
table: "submission_details",
column: "exam_question_id",
principalTable: "exam_questions",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_submissions_exams_exam_id",
table: "submissions",
column: "exam_id",
principalTable: "exams",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_exam_attachments_exams_exam_id",
table: "exam_attachments");
migrationBuilder.DropForeignKey(
name: "FK_exam_questions_QuestionContexts_description",
table: "exam_questions");
migrationBuilder.DropForeignKey(
name: "FK_exam_questions_exam_questions_parent_question_group_id",
table: "exam_questions");
migrationBuilder.DropForeignKey(
name: "FK_exam_questions_question_types_QuestionTypeId",
table: "exam_questions");
migrationBuilder.DropForeignKey(
name: "FK_exam_questions_questions_question_id",
table: "exam_questions");
migrationBuilder.DropForeignKey(
name: "FK_exams_AspNetUsers_created_by",
table: "exams");
migrationBuilder.DropForeignKey(
name: "FK_exams_exam_questions_exam_struct_id",
table: "exams");
migrationBuilder.DropForeignKey(
name: "FK_exams_exam_type_exam_type_id",
table: "exams");
migrationBuilder.DropForeignKey(
name: "FK_exams_subjects_subject_id",
table: "exams");
migrationBuilder.DropForeignKey(
name: "FK_submission_details_exam_questions_exam_question_id",
table: "submission_details");
migrationBuilder.DropForeignKey(
name: "FK_submissions_exams_exam_id",
table: "submissions");
migrationBuilder.DropPrimaryKey(
name: "PK_exams",
table: "exams");
migrationBuilder.DropPrimaryKey(
name: "PK_exam_questions",
table: "exam_questions");
migrationBuilder.DropPrimaryKey(
name: "PK_exam_attachments",
table: "exam_attachments");
migrationBuilder.DropColumn(
name: "exam_struct_type",
table: "exam_questions");
migrationBuilder.RenameTable(
name: "exams",
newName: "assignments");
migrationBuilder.RenameTable(
name: "exam_questions",
newName: "assignment_questions");
migrationBuilder.RenameTable(
name: "exam_attachments",
newName: "assignment_attachments");
migrationBuilder.RenameColumn(
name: "exam_question_id",
table: "submission_details",
newName: "assignment_question_id");
migrationBuilder.RenameIndex(
name: "IX_submission_details_exam_question_id",
table: "submission_details",
newName: "IX_submission_details_assignment_question_id");
migrationBuilder.RenameIndex(
name: "IX_exams_subject_id",
table: "assignments",
newName: "IX_assignments_subject_id");
migrationBuilder.RenameIndex(
name: "IX_exams_exam_type_id",
table: "assignments",
newName: "IX_assignments_exam_type_id");
migrationBuilder.RenameIndex(
name: "IX_exams_exam_struct_id",
table: "assignments",
newName: "IX_assignments_exam_struct_id");
migrationBuilder.RenameIndex(
name: "IX_exams_created_by",
table: "assignments",
newName: "IX_assignments_created_by");
migrationBuilder.RenameIndex(
name: "IX_exam_questions_QuestionTypeId",
table: "assignment_questions",
newName: "IX_assignment_questions_QuestionTypeId");
migrationBuilder.RenameIndex(
name: "IX_exam_questions_question_id",
table: "assignment_questions",
newName: "IX_assignment_questions_question_id");
migrationBuilder.RenameIndex(
name: "IX_exam_questions_parent_question_group_id",
table: "assignment_questions",
newName: "IX_assignment_questions_parent_question_group_id");
migrationBuilder.RenameIndex(
name: "IX_exam_questions_description",
table: "assignment_questions",
newName: "IX_assignment_questions_description");
migrationBuilder.RenameColumn(
name: "exam_id",
table: "assignment_attachments",
newName: "assignment_id");
migrationBuilder.RenameIndex(
name: "IX_exam_attachments_exam_id",
table: "assignment_attachments",
newName: "IX_assignment_attachments_assignment_id");
migrationBuilder.AlterColumn<byte>(
name: "TotalScore",
table: "submissions",
type: "tinyint unsigned",
nullable: false,
oldClrType: typeof(float),
oldType: "float");
migrationBuilder.AddPrimaryKey(
name: "PK_assignments",
table: "assignments",
column: "id");
migrationBuilder.AddPrimaryKey(
name: "PK_assignment_questions",
table: "assignment_questions",
column: "id");
migrationBuilder.AddPrimaryKey(
name: "PK_assignment_attachments",
table: "assignment_attachments",
column: "id");
migrationBuilder.AddForeignKey(
name: "FK_assignment_attachments_assignments_assignment_id",
table: "assignment_attachments",
column: "assignment_id",
principalTable: "assignments",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_assignment_questions_QuestionContexts_description",
table: "assignment_questions",
column: "description",
principalTable: "QuestionContexts",
principalColumn: "Id");
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_assignment_questions_question_types_QuestionTypeId",
table: "assignment_questions",
column: "QuestionTypeId",
principalTable: "question_types",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_assignment_questions_questions_question_id",
table: "assignment_questions",
column: "question_id",
principalTable: "questions",
principalColumn: "id");
migrationBuilder.AddForeignKey(
name: "FK_assignments_AspNetUsers_created_by",
table: "assignments",
column: "created_by",
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_assignments_assignment_questions_exam_struct_id",
table: "assignments",
column: "exam_struct_id",
principalTable: "assignment_questions",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_assignments_exam_type_exam_type_id",
table: "assignments",
column: "exam_type_id",
principalTable: "exam_type",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_assignments_subjects_subject_id",
table: "assignments",
column: "subject_id",
principalTable: "subjects",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_submission_details_assignment_questions_assignment_question_~",
table: "submission_details",
column: "assignment_question_id",
principalTable: "assignment_questions",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_submissions_assignments_exam_id",
table: "submissions",
column: "exam_id",
principalTable: "assignments",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
}
}
}

View File

@@ -9,10 +9,11 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using TechHelper.Features;
using TechHelper.Services;
using TechHelper.Server.Services;
using TechHelper.Server.Repositories;
using Microsoft.OpenApi.Models;
using TechHelper.Services.Beta;
using TechHelper.Server.Context;
using TechHelper.Server.Repository;
/// <summary>
/// TechHelper 服务器应用程序的主入口点
@@ -24,22 +25,28 @@ builder.Services.AddControllers();
// 2. 数据库服务 (DbContext)
builder.Services.AddDbContext<ApplicationContext>(options =>
options.UseMySql(
options
.UseLazyLoadingProxies()
.UseMySql(
builder.Configuration.GetConnectionString("XSDB"),
ServerVersion.AutoDetect(builder.Configuration.GetConnectionString("XSDB"))
)
).AddUnitOfWork<ApplicationContext>()
.AddCustomRepository<Assignment, AssignmentRepository>()
.AddCustomRepository<AssignmentAttachment, AssignmentAttachmentRepository>()
.AddCustomRepository<AssignmentQuestion, AssignmentQuestionRepository>()
.AddCustomRepository<Exam, AssignmentRepository>()
.AddCustomRepository<ExamAttachment, AssignmentAttachmentRepository>()
.AddCustomRepository<ExamQuestion, ExamQuestionRepository>()
.AddCustomRepository<Class, ClassRepository>()
.AddCustomRepository<ClassStudent, ClassStudentRepository>()
.AddCustomRepository<ClassTeacher, ClassTeacherRepository>()
.AddCustomRepository<ClassUser, ClassUserRepository>()
.AddCustomRepository<Question, QuestionRepository>()
.AddCustomRepository<QuestionContext, QuestionContextRepository>()
.AddCustomRepository<Submission, SubmissionRepository>()
.AddCustomRepository<Subject, SubjectRepository>()
.AddCustomRepository<ExamType, ExamTypeRepository>()
.AddCustomRepository<QuestionType, QuestionTypeRepository>()
.AddCustomRepository<User, UserRepository>()
.AddCustomRepository<Global, GlobalRepository>();
.AddCustomRepository<KeyPoint, KeyPointRepository>()
.AddCustomRepository<Lesson, LessonRepository>()
.AddCustomRepository<Textbook, TextbookRepository>();
builder.Services.AddAutoMapper(typeof(AutoMapperProFile).Assembly);
@@ -55,10 +62,11 @@ builder.Services.AddIdentity<User, IdentityRole<Guid>>(opt =>
{
opt.User.AllowedUserNameCharacters = "";
opt.Lockout.AllowedForNewUsers = true;
opt.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(2);
opt.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
opt.Lockout.MaxFailedAccessAttempts = 3;
})
.AddEntityFrameworkStores<ApplicationContext>()
.AddRoles<IdentityRole<Guid>>()
.AddEntityFrameworkStores<ApplicationContext>()
.AddDefaultTokenProviders();
builder.Services.Configure<DataProtectionTokenProviderOptions>(Options =>
{
@@ -81,7 +89,7 @@ builder.Services.AddAuthentication(options =>
ValidateAudience = true, // 验证受众
ValidateLifetime = true, // 验证令牌有效期
ValidateIssuerSigningKey = true, // 验证签名密钥
ValidIssuer = jwtSettings["validIssuer"], // 合法的签发人
ValidAudience = jwtSettings["validAudience"], // 合法的受众
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["securityKey"])) // 签名密钥
@@ -90,15 +98,23 @@ builder.Services.AddAuthentication(options =>
builder.Services.AddScoped<IAuthenticationService, AuthenticationService>();
builder.Services.AddScoped<IEmailSender, QEmailSender>();
builder.Services.AddTransient<IUserRegistrationService, UserRegistrationService>();
builder.Services.AddScoped<IClassService, ClassService>();
builder.Services.AddScoped<IExamService, ExamService>();
builder.Services.AddScoped<IUserSerivces, UserServices>();
builder.Services.AddScoped<ISubmissionServices, SubmissionServices>();
builder.Services.AddScoped<IStudentSubmissionService, StudentSubmissionService>();
builder.Services.AddScoped<IStudentSubmissionDetailService, StudentSubmissionDetailService>();
builder.Services.AddScoped<IExamRepository, ExamRepository>();
builder.Services.AddScoped<INoteService, NoteService>();
builder.Services.AddScoped<ISubmissionService, SubmissionService>();
builder.Services.AddScoped<ISubmissionDetailService, SubmissionDetailService>();
builder.Services.AddScoped<IExamRepository, ExamRepository>();
builder.Services.AddScoped<ISchoolService, SchoolService>();
builder.Services.AddScoped<IGradeService, GradeService>();
builder.Services.AddScoped<ISubjectService, SubjectService>();
builder.Services.AddScoped<IExamTypeService, ExamTypeService>();
builder.Services.AddScoped<IQuestionTypeService, QuestionTypeService>();
builder.Services.AddScoped<IQuestionService, QuestionService>();
builder.Services.AddScoped<IExamQuestionService, ExamQuestionService>();
builder.Services.AddScoped<IKeyPointService, KeyPointService>();
builder.Services.AddScoped<ILessonService, LessonService>();
builder.Services.AddScoped<ITextbookService, TextbookService>();
builder.Services.AddEndpointsApiExplorer();
@@ -108,11 +124,11 @@ builder.Services.AddSwaggerGen(c =>
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Name = "Authorization",
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header,
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\"",
});
@@ -124,27 +140,28 @@ builder.Services.AddSwaggerGen(c =>
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
Id = "Bearer"
}
},
new string[] {}
}
}
});
});
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowSpecificOrigin",
builder => builder
.WithOrigins("https://localhost:7047", "http://localhost:7047", "https://localhost:5001", "http://localhost:5001")
.WithOrigins("https://localhost:7047", "http://localhost:7047", "https://localhost:5001", "http://localhost:5001")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials());
.AllowCredentials());
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (/*app.Environment.IsDevelopment()*/true)
{
@@ -157,6 +174,21 @@ app.UseHttpsRedirection();
app.UseAuthorization();
using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var roleManager = services.GetRequiredService<RoleManager<IdentityRole<Guid>>>();
await DbInitializer.SeedRoles(roleManager);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while seeding the database.");
}
}
app.MapControllers();
app.Run();

View File

@@ -9,18 +9,18 @@ namespace TechHelper.Server.Repositories
public class ExamRepository : IExamRepository
{
private readonly IUnitOfWork _unitOfWork;
private readonly IRepository<Assignment> _assignmentRepo;
private readonly IRepository<Exam> _assignmentRepo;
private readonly IRepository<Question> _questionRepo;
private readonly IRepository<AssignmentQuestion> _assignQuestionRepo;
private readonly IRepository<ExamQuestion> _assignQuestionRepo;
public ExamRepository(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
_assignmentRepo = _unitOfWork.GetRepository<Assignment>();
_assignQuestionRepo = _unitOfWork.GetRepository<AssignmentQuestion>();
_assignmentRepo = _unitOfWork.GetRepository<Exam>();
_assignQuestionRepo = _unitOfWork.GetRepository<ExamQuestion>();
}
public async Task<Assignment?> GetFullExamByIdAsync(Guid assignmentId)
public async Task<Exam?> GetFullExamByIdAsync(Guid assignmentId)
{
var result = await _assignmentRepo.GetFirstOrDefaultAsync(
predicate:
@@ -35,12 +35,12 @@ namespace TechHelper.Server.Repositories
}
public async Task<AssignmentQuestion?> GetNeed(Guid id)
public async Task<ExamQuestion?> GetNeed(Guid id)
{
var result = await _assignQuestionRepo.GetFirstOrDefaultAsync(
predicate: aq => aq.Id == id,
include: i => i
.Include(aq => aq.ChildrenAssignmentQuestion)
.Include(aq => aq.ChildExamQuestions)
.Include(aq => aq.Question)
.ThenInclude(q => q.Lesson)
.Include(aq => aq.Question)
@@ -52,8 +52,8 @@ namespace TechHelper.Server.Repositories
return null;
}
var loadedChildren = new List<AssignmentQuestion>();
foreach (var child in result.ChildrenAssignmentQuestion)
var loadedChildren = new List<ExamQuestion>();
foreach (var child in result.ChildExamQuestions)
{
var loadedChild = await GetNeed(child.Id);
if (loadedChild != null)
@@ -61,25 +61,25 @@ namespace TechHelper.Server.Repositories
loadedChildren.Add(loadedChild);
}
}
result.ChildrenAssignmentQuestion = loadedChildren;
result.ChildExamQuestions = loadedChildren;
return result;
}
public async Task<IEnumerable<Assignment>> GetExamPreviewsByUserAsync(Guid userId)
public async Task<IEnumerable<Exam>> GetExamPreviewsByUserAsync(Guid userId)
{
return await _assignmentRepo.GetAllAsync(
predicate: a => a.CreatorId == userId && !a.IsDeleted);
}
public async Task AddAsync(Assignment assignment)
public async Task AddAsync(Exam assignment)
{
await _assignmentRepo.InsertAsync(assignment);
}
public async Task AddAsync(AssignmentQuestion assignment)
public async Task AddAsync(ExamQuestion assignment)
{
}
@@ -87,21 +87,17 @@ namespace TechHelper.Server.Repositories
{
}
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)
public async Task<IEnumerable<Exam>> GetAllSubmissionPreviewsByUserAsync(Guid id)
{
var submissions = await _unitOfWork.GetRepository<Submission>().GetAllAsync(predicate: s => s.StudentId == id, include: i => i.Include(s => s.Assignment));
var submissions = await _unitOfWork.GetRepository<Submission>().GetAllAsync(predicate: s => s.StudentId == id, include: i => i.Include(s => s.Exam));
if (submissions == null || !submissions.Any())
return Enumerable.Empty<Assignment>();
return submissions.ToList().Select(s => s.Assignment).Where(a => a != null).ToList();
return Enumerable.Empty<Exam>();
return submissions.ToList().Select(s => s.Exam).Where(a => a != null).ToList();
}
}
}

View File

@@ -10,30 +10,29 @@ namespace TechHelper.Server.Repositories
/// </summary>
/// <param name="assignmentId">试卷ID</param>
/// <returns>完整的 Assignment 实体,如果找不到则返回 null。</returns>
Task<Assignment?> GetFullExamByIdAsync(Guid assignmentId);
Task<Exam?> GetFullExamByIdAsync(Guid assignmentId);
/// <summary>
/// 获取指定用户创建的所有试卷的预览信息。
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns>Assignment 实体集合。</returns>
Task<IEnumerable<Assignment>> GetExamPreviewsByUserAsync(Guid userId);
Task<IEnumerable<Exam>> GetExamPreviewsByUserAsync(Guid userId);
/// <summary>
/// 向数据库添加一个新的试卷。
/// </summary>
/// <param name="assignment">要添加的试卷实体。</param>
Task AddAsync(Assignment assignment);
Task AddAsync(Exam assignment);
Task AddAsync(Submission submission);
Task AddAsync(AssignmentQuestion assignment);
Task AddAsync(ExamQuestion assignment);
Task AddAsync(Question assignment);
Task AddAsync(AssignmentClass assignment);
Task<IEnumerable<Assignment>> GetAllSubmissionPreviewsByUserAsync(Guid id);
Task<IEnumerable<Exam>> GetAllSubmissionPreviewsByUserAsync(Guid id);
}
}

View File

@@ -5,7 +5,7 @@ using TechHelper.Context;
namespace TechHelper.Repository
{
public class AssignmentAttachmentRepository : Repository<AssignmentAttachment>, IRepository<AssignmentAttachment>
public class AssignmentAttachmentRepository : Repository<ExamAttachment>, IRepository<ExamAttachment>
{
public AssignmentAttachmentRepository(ApplicationContext dbContext) : base(dbContext)
{

View File

@@ -1,14 +0,0 @@
using Entities.Contracts;
using Microsoft.EntityFrameworkCore;
using SharedDATA.Api;
using TechHelper.Context;
namespace TechHelper.Repository
{
public class AssignmentClassRepository : Repository<AssignmentClass>, IRepository<AssignmentClass>
{
public AssignmentClassRepository(ApplicationContext dbContext) : base(dbContext)
{
}
}
}

View File

@@ -5,7 +5,7 @@ using TechHelper.Context;
namespace TechHelper.Repository
{
public class AssignmentQuestionRepository : Repository<AssignmentQuestion>, IRepository<AssignmentQuestion>
public class AssignmentQuestionRepository : Repository<ExamQuestion>, IRepository<ExamQuestion>
{
public AssignmentQuestionRepository(ApplicationContext dbContext) : base(dbContext)
{

View File

@@ -5,7 +5,7 @@ using TechHelper.Context;
namespace TechHelper.Repository
{
public class AssignmentRepository : Repository<Assignment>, IRepository<Assignment>
public class AssignmentRepository : Repository<Exam>, IRepository<Exam>
{
public AssignmentRepository(ApplicationContext dbContext) : base(dbContext)
{

View File

@@ -1,14 +0,0 @@
using Entities.Contracts;
using Microsoft.EntityFrameworkCore;
using SharedDATA.Api;
using TechHelper.Context;
namespace TechHelper.Repository
{
public class ClassStudentRepository : Repository<ClassStudent>, IRepository<ClassStudent>
{
public ClassStudentRepository(ApplicationContext dbContext) : base(dbContext)
{
}
}
}

View File

@@ -1,14 +0,0 @@
using Entities.Contracts;
using Microsoft.EntityFrameworkCore;
using SharedDATA.Api;
using TechHelper.Context;
namespace TechHelper.Repository
{
public class ClassTeacherRepository : Repository<ClassTeacher>, IRepository<ClassTeacher>
{
public ClassTeacherRepository(ApplicationContext dbContext) : base(dbContext)
{
}
}
}

View File

@@ -5,13 +5,10 @@ using TechHelper.Context;
namespace TechHelper.Repository
{
public class GlobalRepository : Repository<Global>, IRepository<Global>
public class ClassUserRepository : Repository<ClassUser>, IRepository<ClassUser>
{
public GlobalRepository(ApplicationContext dbContext) : base(dbContext)
public ClassUserRepository(ApplicationContext dbContext) : base(dbContext)
{
}
}
}

View File

@@ -0,0 +1,14 @@
using Entities.Contracts;
using Microsoft.EntityFrameworkCore;
using SharedDATA.Api;
using TechHelper.Context;
namespace TechHelper.Repository
{
public class ExamQuestionRepository : Repository<ExamQuestion>, IRepository<ExamQuestion>
{
public ExamQuestionRepository(ApplicationContext dbContext) : base(dbContext)
{
}
}
}

View File

@@ -0,0 +1,14 @@
using Entities.Contracts;
using Microsoft.EntityFrameworkCore;
using SharedDATA.Api;
using TechHelper.Context;
namespace TechHelper.Repository
{
public class ExamTypeRepository : Repository<ExamType>, IRepository<ExamType>
{
public ExamTypeRepository(ApplicationContext dbContext) : base(dbContext)
{
}
}
}

View File

@@ -0,0 +1,13 @@
using Entities.Contracts;
using SharedDATA.Api;
using TechHelper.Context;
namespace TechHelper.Repository
{
public class KeyPointRepository : Repository<KeyPoint>, IRepository<KeyPoint>
{
public KeyPointRepository(ApplicationContext context) : base(context)
{
}
}
}

View File

@@ -0,0 +1,18 @@
using Entities.Contracts;
using SharedDATA.Api;
using System.Linq.Expressions;
using TechHelper.Context;
using TechHelper.Server.Repository;
namespace TechHelper.Server.Repository
{
/// <summary>
/// Lesson仓储实现类
/// </summary>
public class LessonRepository : Repository<Lesson>, IRepository<Lesson>
{
public LessonRepository(ApplicationContext context) : base(context)
{
}
}
}

View File

@@ -0,0 +1,14 @@
using Entities.Contracts;
using Microsoft.EntityFrameworkCore;
using SharedDATA.Api;
using TechHelper.Context;
namespace TechHelper.Repository
{
public class QuestionTypeRepository : Repository<QuestionType>, IRepository<QuestionType>
{
public QuestionTypeRepository(ApplicationContext dbContext) : base(dbContext)
{
}
}
}

View File

@@ -0,0 +1,14 @@
using Entities.Contracts;
using Microsoft.EntityFrameworkCore;
using SharedDATA.Api;
using TechHelper.Context;
namespace TechHelper.Repository
{
public class SubjectRepository : Repository<Subject>, IRepository<Subject>
{
public SubjectRepository(ApplicationContext dbContext) : base(dbContext)
{
}
}
}

View File

@@ -0,0 +1,21 @@
using Entities.Contracts;
using Microsoft.EntityFrameworkCore;
using SharedDATA.Api;
using TechHelper.Context;
namespace TechHelper.Repository
{
/// <summary>
/// 教材仓储实现类
/// </summary>
public class TextbookRepository : Repository<Textbook>, IRepository<Textbook>
{
/// <summary>
/// 初始化教材仓储
/// </summary>
/// <param name="dbContext">数据库上下文</param>
public TextbookRepository(ApplicationContext dbContext) : base(dbContext)
{
}
}
}

View File

@@ -0,0 +1,319 @@
using AutoMapper;
using Entities.Contracts;
using Entities.DTO;
using Entities.DTO.Class;
using Microsoft.EntityFrameworkCore;
using SharedDATA.Api;
using TechHelper.Repository;
namespace TechHelper.Services.Beta
{
public class ClassService : IClassService
{
private readonly IUnitOfWork _work;
private readonly IMapper _mapper;
public ClassService(IUnitOfWork work, IMapper mapper)
{
_work = work;
_mapper = mapper;
}
public async Task<ApiResponse> GetAllAsync(QueryParameter query)
{
try
{
var repository = _work.GetRepository<Class>();
if (query.Search != null && !string.IsNullOrWhiteSpace(query.Search))
{
var classes = await repository.GetPagedListAsync(
predicate: c => c.ClassName.Contains(query.Search),
pageSize: query.PageSize,
pageIndex: query.PageIndex
);
var classDtosFiltered = _mapper.Map<IEnumerable<ClassDto>>(classes.Items);
return new ApiResponse(true, classDtosFiltered);
}
else
{
var classes = await repository.GetPagedListAsync(
pageSize: query.PageSize,
pageIndex: query.PageIndex
);
var classDtos = _mapper.Map<IEnumerable<ClassDto>>(classes.Items);
return new ApiResponse(true, classDtos);
}
}
catch (Exception ex)
{
return new ApiResponse($"获取所有班级时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> GetAsync(Guid id)
{
try
{
var @class = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
predicate: c => c.Id == id,
include: i => i.Include(c => c.Grade).Include(c => c.HeadTeacher));
if (@class == null)
{
return new ApiResponse("班级未找到。");
}
var classDto = _mapper.Map<ClassDto>(@class);
return new ApiResponse(true, classDto);
}
catch (Exception ex)
{
return new ApiResponse($"获取班级时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> AddAsync(ClassDto model)
{
try
{
// 检查是否已存在相同年级下的同名班级
var existingClass = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
predicate: c => c.GradeId == model.GradeId && (c.ClassName == model.ClassName || c.Index == model.Index));
if (existingClass != null)
{
return new ApiResponse($"在当前年级下,班级 '{model.ClassName}', 序号 '{model.Index}' 已存在。 请检查你的班级名称和序号, 如有问题请联系管理员.");
}
var @class = _mapper.Map<Class>(model);
await _work.GetRepository<Class>().InsertAsync(@class);
if (await _work.SaveChangesAsync() > 0)
{
return new ApiResponse(true, _mapper.Map<ClassDto>(@class));
}
return new ApiResponse("添加班级失败。");
}
catch (Exception ex)
{
return new ApiResponse($"添加班级时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> UpdateAsync(ClassDto model)
{
try
{
var existingClass = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
predicate: c => c.Id == model.Id);
if (existingClass == null)
{
return new ApiResponse("班级未找到。");
}
_mapper.Map(model, existingClass);
_work.GetRepository<Class>().Update(existingClass);
if (await _work.SaveChangesAsync() > 0)
{
return new ApiResponse(true, _mapper.Map<ClassDto>(existingClass));
}
return new ApiResponse("更新班级失败。");
}
catch (Exception ex)
{
return new ApiResponse($"更新班级时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> DeleteAsync(Guid id)
{
try
{
var existingClass = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
predicate: c => c.Id == id);
if (existingClass == null)
{
return new ApiResponse("班级未找到。");
}
_work.GetRepository<Class>().Delete(existingClass);
if (await _work.SaveChangesAsync() > 0)
{
return new ApiResponse(true, "班级删除成功。");
}
return new ApiResponse("删除班级失败。");
}
catch (Exception ex)
{
return new ApiResponse($"删除班级时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> GetClassStudentsAsync(Guid classId)
{
try
{
var classEntity = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
predicate: c => c.Id == classId);
if (classEntity == null)
{
return new ApiResponse("班级未找到。");
}
var students = classEntity.Students
.Where(u => !u.IsDeleted)
.Select(u => u.User)
.ToList();
var StudentsDto = _mapper.Map<IEnumerable<UserListDto>>(students);
return new ApiResponse(true, StudentsDto);
}
catch (Exception ex)
{
return new ApiResponse($"获取班级学生时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> ValidateClassRegistration(ClassValidDto user)
{
try
{
// 验证学校是否存在
var schoolRepository = _work.GetRepository<School>();
var school = await schoolRepository.GetFirstOrDefaultAsync(
predicate: s => s.SchoolName == user.SchoolName);
if (school == null)
{
return new ApiResponse("学校未找到。");
}
// 验证年级是否存在
var gradeRepository = _work.GetRepository<Grade>();
var grade = await gradeRepository.GetFirstOrDefaultAsync(
predicate: g => g.SchoolId == school.Id && g.GradeLevel == user.Grade);
if (grade == null)
{
return new ApiResponse("年级未找到。");
}
// 验证班级是否存在
var classRepository = _work.GetRepository<Class>();
var classEntity = await classRepository.GetFirstOrDefaultAsync(
predicate: c => c.GradeId == grade.Id && c.Index == user.Class && !c.IsDeleted);
if (classEntity == null)
{
return new ApiResponse("班级未找到。");
}
// 返回验证成功的班级信息
return new ApiResponse(true, classEntity.Id);
}
catch (Exception ex)
{
return new ApiResponse($"验证班级信息时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> UserRegister(RegisterUserToClassDto user)
{
try
{
// 获取班级实体
var classRepository = _work.GetRepository<Class>();
var classEntity = await classRepository.GetFirstOrDefaultAsync(
predicate: c => c.Id == user.ClassId);
if (classEntity == null)
{
return new ApiResponse("检查你的班级输入,没有该班级。");
}
// 检查用户是否已经在该班级中
var existingClassUser = classEntity.ClassUsers.FirstOrDefault(u => u.UserId == user.UserId);
if (existingClassUser != null )
{
return new ApiResponse("用户已经在该班级中。");
}
await _work.GetRepository<ClassUser>().InsertAsync(
new ClassUser { ClassId = user.ClassId, UserId = user.UserId, EnrollmentDate = DateTime.Now });
if (await _work.SaveChangesAsync() > 0)
{
return new ApiResponse(true, "用户成功注册到班级。");
}
return new ApiResponse("用户注册到班级失败。");
}
catch (Exception ex)
{
return new ApiResponse($"用户注册到班级时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> GetUserInjoinedClasses(Guid user)
{
try
{
var userInfo = await _work.GetRepository<User>().GetFirstOrDefaultAsync(predicate:
u => u.Id == user,include: i => i
.Include(u => u.UserInjoinedClass)
.ThenInclude(c => c.Class)
.ThenInclude(cs => cs.Grade));
var schoolName = userInfo.UserInjoinedClass.First().Class.Grade.School.SchoolName;
var userClassInfo = userInfo.UserInjoinedClass.Select(c => c.Class);
var userClassDto = userClassInfo.Select(c => new UserClassInfoDto(c.Id, c.Index, c.Grade.GradeLevel));
var result = new UserClassDetailInfoDto(userClassDto, schoolName);
return ApiResponse.Success(result: result);
}
catch(Exception ex)
{
return ApiResponse.Error($"获取用户班级信息时发生错误: {ex.Message}");
}
}
public Task<ApiResponse> GetUserClassRole(Guid id)
{
throw new NotImplementedException();
}
public async Task<ApiResponse> AdminAddAsync(ClassCreateDto model)
{
try
{
// 检查是否已存在相同年级下的同名班级
var existingClass = await _work.GetRepository<Class>().GetFirstOrDefaultAsync(
predicate: c => c.Grade.GradeLevel == model.Grade.GradeLevel && (c.ClassName == model.ClassName || c.Index == model.Index));
if (existingClass != null)
{
return new ApiResponse($"在当前年级下,班级 '{model.ClassName}', 序号 '{model.Index}' 已存在。 请检查你的班级名称和序号, 如有问题请联系管理员.");
}
var @class = _mapper.Map<Class>(model);
await _work.GetRepository<Class>().InsertAsync(@class);
if (await _work.SaveChangesAsync() > 0)
{
return new ApiResponse(true, _mapper.Map<ClassDto>(@class));
}
return new ApiResponse("添加班级失败。");
}
catch (Exception ex)
{
return new ApiResponse($"添加班级时发生错误: {ex.Message}");
}
}
}
}

View File

@@ -0,0 +1,16 @@
using Entities.DTO;
using Entities.DTO.Class;
using SharedDATA.Api;
namespace TechHelper.Services.Beta
{
public interface IClassService : IBaseService<ClassDto, Guid>
{
Task<ApiResponse> GetClassStudentsAsync(Guid classId);
Task<ApiResponse> UserRegister(RegisterUserToClassDto user);
Task<ApiResponse> ValidateClassRegistration(ClassValidDto user);
Task<ApiResponse> GetUserInjoinedClasses(Guid user);
Task<ApiResponse> GetUserClassRole(Guid id);
Task<ApiResponse> AdminAddAsync(ClassCreateDto dto);
}
}

View File

@@ -1,6 +1,7 @@
using AutoMapper;
using Entities.Contracts;
using Entities.DTO;
using Entities.DTO.Class;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Org.BouncyCastle.Crypto;
@@ -41,7 +42,7 @@ namespace TechHelper.Services
}
// 实现 IBaseService<ClassDto, int>.DeleteAsync
public async Task<ApiResponse> DeleteAsync(Guid id) // ID 类型现在是 int
public async Task<ApiResponse> DeleteAsync(Guid id)
{
try
{

View File

@@ -0,0 +1,196 @@
using AutoMapper;
using Entities.Contracts;
using Entities.DTO;
using Microsoft.EntityFrameworkCore;
using SharedDATA.Api;
using TechHelper.Services.Beta;
using static TechHelper.Services.Beta.IExamQuestionService;
namespace TechHelper.Services.Beta
{
public class ExamQuestionService : IExamQuestionService
{
private readonly IUnitOfWork _work;
private readonly IMapper _mapper;
private readonly IClassService _classService;
public ExamQuestionService(IUnitOfWork work, IMapper mapper, IClassService classService)
{
_work = work;
_mapper = mapper;
_classService = classService;
}
public async Task<ApiResponse> GetAllAsync(QueryParameter query)
{
try
{
var repository = _work.GetRepository<ExamQuestion>();
if (query.Search != null && !string.IsNullOrWhiteSpace(query.Search))
{
var examQuestions = await repository.GetPagedListAsync(
predicate: eq => eq.Title.Contains(query.Search) && eq.ParentExamQuestionId == null,
pageSize: query.PageSize,
pageIndex: query.PageIndex
);
var examQuestionDtosFiltered = _mapper.Map<IEnumerable<ExamQuestionDto>>(examQuestions.Items);
return new ApiResponse(true, examQuestionDtosFiltered);
}
else
{
var examQuestions = await repository.GetPagedListAsync(
predicate: eq => eq.ParentExamQuestionId == null,
pageSize: query.PageSize,
pageIndex: query.PageIndex
);
var examQuestionDtos = _mapper.Map<IEnumerable<ExamQuestionDto>>(examQuestions.Items);
return new ApiResponse(true, examQuestionDtos);
}
}
catch (Exception ex)
{
return new ApiResponse($"获取所有考试题目时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> GetAsync(Guid id)
{
try
{
var examQuestion = await _work.GetRepository<ExamQuestion>().GetFirstOrDefaultAsync(
predicate: eq => eq.Id == id);
if (examQuestion == null)
{
return new ApiResponse("考试题目未找到。");
}
var examQuestionDto = _mapper.Map<ExamQuestionDto>(examQuestion);
return new ApiResponse(true, examQuestionDto);
}
catch (Exception ex)
{
return new ApiResponse($"获取考试题目时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> AddAsync(ExamQuestionDto model)
{
try
{
// 检查是否已存在相同考试和题目的组合
var existingExamQuestion = await _work.GetRepository<ExamQuestion>().GetFirstOrDefaultAsync(
predicate: eq => eq.Id == model.Id/* && eq.QuestionId == model.Question.Id*/);
if (existingExamQuestion != null)
{
return new ApiResponse($"该题目已在此考试中存在。");
}
var examQuestion = _mapper.Map<ExamQuestion>(model);
await _work.GetRepository<ExamQuestion>().InsertAsync(examQuestion);
if (await _work.SaveChangesAsync() > 0)
{
return new ApiResponse(true, examQuestion.Id);
}
return new ApiResponse("添加考试题目失败。");
}
catch (Exception ex)
{
return new ApiResponse($"添加考试题目时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> UpdateAsync(ExamQuestionDto model)
{
try
{
var existingExamQuestion = await _work.GetRepository<ExamQuestion>().GetFirstOrDefaultAsync(
predicate: eq => eq.Id == model.Id);
if (existingExamQuestion == null)
{
return new ApiResponse("考试题目未找到。");
}
// 检查是否要修改为已存在的考试题目组合(排除当前记录)
var examQuestionWithSameCombination = await _work.GetRepository<ExamQuestion>().GetFirstOrDefaultAsync(
predicate: eq => eq.Id == model.Id /*&& eq.QuestionId == model.QuestionId*/ && eq.Id != model.Id);
if (examQuestionWithSameCombination != null)
{
return new ApiResponse($"该题目与考试的组合已存在。");
}
_mapper.Map(model, existingExamQuestion);
_work.GetRepository<ExamQuestion>().Update(existingExamQuestion);
if (await _work.SaveChangesAsync() > 0)
{
var examQuestionDto = _mapper.Map<ExamQuestionDto>(existingExamQuestion);
return new ApiResponse(true, examQuestionDto);
}
return new ApiResponse("更新考试题目失败。");
}
catch (Exception ex)
{
return new ApiResponse($"更新考试题目时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> DeleteAsync(Guid id)
{
try
{
var existingExamQuestion = await _work.GetRepository<ExamQuestion>().GetFirstOrDefaultAsync(
predicate: eq => eq.Id == id);
if (existingExamQuestion == null)
{
return new ApiResponse("考试题目未找到。");
}
_work.GetRepository<ExamQuestion>().Delete(existingExamQuestion);
if (await _work.SaveChangesAsync() > 0)
{
return new ApiResponse(true, "考试题目删除成功。");
}
return new ApiResponse("删除考试题目失败。");
}
catch (Exception ex)
{
return new ApiResponse($"删除考试题目时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> GetQuestionDependy(QuesitionDenpendceyRequst request)
{
try
{
var classStudentsResponse = await _classService.GetClassStudentsAsync(request.ClassId);
if (!classStudentsResponse.Status) return ApiResponse.Error(classStudentsResponse.Message);
var classStudents = classStudentsResponse.Result as IEnumerable<UserListDto>;
if (classStudents == null) return ApiResponse.Error("班级学生列表为空。");
var submissionResult = await _work.GetRepository<SubmissionDetail>().GetAllAsync(predicate: sd => sd.ExamQuestionId == request.ExamQuestioId );
var submission = submissionResult.Where(s => classStudents.Any(c => c.Id == s.StudentId));
var errorStudents = submission.Select(s => s.Student);
var scores = submission.Select(s => s.PointsAwarded);
var lesson = submission.FirstOrDefault()?.ExamQuestion?.Question?.Lesson ?? null;
var lessonDto = _mapper.Map<LessonDto>(lesson);
var ErrorStudentDtro = _mapper.Map<IEnumerable<UserListDto>>(errorStudents);
return ApiResponse.Success("获取成功", new QuestionDependecyDto(lessonDto, scores, ErrorStudentDtro));
}
catch (Exception ex)
{
return ApiResponse.Error($"获取考试题目密度时发生错误: {ex.Message}");
}
}
}
}

View File

@@ -0,0 +1,341 @@
using AutoMapper;
using Entities.Contracts;
using Entities.DTO;
using Microsoft.EntityFrameworkCore;
using Microsoft.VisualBasic;
using SharedDATA.Api;
using System.Linq;
using TechHelper.Context;
using TechHelper.Server.Repositories;
using TechHelper.Services.Beta;
using static TechHelper.Services.Beta.IExamService;
namespace TechHelper.Services.Beta
{
public class ExamService : IExamService
{
private readonly IUnitOfWork _unitOfWork;
private readonly ISubmissionService _submissionService;
private readonly IClassService _classService;
private readonly IMapper _mapper;
public ExamService(IUnitOfWork unitOfWork, IMapper mapper, IClassService classService, ISubmissionService submissionService)
{
_unitOfWork = unitOfWork;
_mapper = mapper;
_classService = classService;
_submissionService = submissionService;
}
public async Task<ApiResponse> CreateExamAsync(ExamDto ExamDto)
{
try
{
Exam newAssi = _mapper.Map<Exam>(ExamDto);
//var context = _unitOfWork.GetDbContext<ApplicationContext>();
//foreach (var entry in context.ChangeTracker.Entries())
//{
// if (entry.State == Microsoft.EntityFrameworkCore.EntityState.Added)
// {
// if (entry.Entity is Question newQues)
// {
// newQues.CreatorId = newAssi.CreatorId;
// }
// }
//}
if (await _unitOfWork.SaveChangesAsync() > 0)
{
return ApiResponse.Success();
}
return ApiResponse.Error("保存失败");
}
catch (Exception ex)
{
return ApiResponse.Error(ex.Message);
}
}
public async Task<ApiResponse> GetAllAsync(QueryParameter query)
{
try
{
var repository = _unitOfWork.GetRepository<Exam>();
if (query.Search != null && !string.IsNullOrWhiteSpace(query.Search))
{
var examQuestions = await repository.GetPagedListAsync(
predicate: eq => eq.Title.Contains(query.Search),
pageSize: query.PageSize,
pageIndex: query.PageIndex
);
var examQuestionDtosFiltered = _mapper.Map<IEnumerable<ExamListDto>>(examQuestions.Items);
return new ApiResponse(true, examQuestionDtosFiltered);
}
else
{
var examQuestions = await repository.GetPagedListAsync(
pageSize: query.PageSize,
pageIndex: query.PageIndex
);
var examQuestionDtos = _mapper.Map<IEnumerable<ExamListDto>>(examQuestions.Items);
return new ApiResponse(true, examQuestionDtos);
}
}
catch (Exception ex)
{
return new ApiResponse($"获取所有考试题目时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> GetAsync(Guid id)
{
try
{
var assignment = await _unitOfWork.GetRepository<Exam>().GetFirstOrDefaultAsync(predicate: a => a.Id == id);
if (assignment == null)
{
return ApiResponse.Error("获取失败");
}
var result = _mapper.Map<ExamDto>(assignment);
return ApiResponse.Success(result: result);
}
catch (Exception ex)
{
return ApiResponse.Error(ex.Message);
}
}
public async Task<ApiResponse> AddAsync(ExamDto model)
{
try
{
var exam = _mapper.Map<Exam>(model);
await _unitOfWork.GetRepository<Exam>().InsertAsync(exam);
if (await _unitOfWork.SaveChangesAsync() > 0)
{
return ApiResponse.Success("创建成功", exam.Id);
}
return ApiResponse.Error("创建失败");
}
catch (Exception ex)
{
return ApiResponse.Error(ex.Message);
}
}
public async Task<ApiResponse> UpdateAsync(ExamDto model)
{
try
{
var existingExam = await _unitOfWork.GetRepository<Exam>().GetFirstOrDefaultAsync(predicate: a => a.Id == model.Id);
if (existingExam == null) return ApiResponse.Error("找不到该试卷");
_mapper.Map(model, existingExam);
_unitOfWork.GetRepository<Exam>().Update(existingExam);
if (await _unitOfWork.SaveChangesAsync() > 0)
{
return ApiResponse.Success("更新成功");
}
return ApiResponse.Error("更新失败");
}
catch (Exception ex)
{
return ApiResponse.Error(ex.Message);
}
}
public async Task<ApiResponse> DeleteAsync(Guid id)
{
try
{
var assignment = await _unitOfWork.GetRepository<Exam>().GetFirstOrDefaultAsync(predicate: a => a.Id == id);
if (assignment == null) return ApiResponse.Error("找不到该试卷");
_unitOfWork.GetRepository<Exam>().Delete(id);
_unitOfWork.GetRepository<ExamQuestion>().Delete(assignment.ExamStructId);
if (await _unitOfWork.SaveChangesAsync() > 0)
{
return ApiResponse.Success();
}
return ApiResponse.Error("删除失败");
}
catch (Exception ex)
{
return ApiResponse.Error($"内部问题,{ex.Message}, InerException{ex.InnerException}");
}
}
public async Task<ApiResponse> AssignmentToAllClassesAsync(AssigExamToClassDto examToClassDto, Guid TeacherId)
{
try
{
var result = await _classService.GetUserInjoinedClasses(TeacherId);
if (result.Status == false) return ApiResponse.Error(result.Message);
var userClass = result.Result as UserClassDetailInfoDto;
if (userClass == null || !userClass.UserClassInfos.Any()) return ApiResponse.Error("教师没有管理任何班级");
var assignment = await _unitOfWork.GetRepository<Exam>().GetFirstOrDefaultAsync(predicate: a => a.Id == examToClassDto.examId);
if (assignment == null) return ApiResponse.Error("没有找到该试卷");
foreach (var classId in userClass.UserClassInfos)
{
await AssignmentToClassAsync(TeacherId, examToClassDto.examId, classId.Id);
}
if (await _unitOfWork.SaveChangesAsync() > 0)
{
return ApiResponse.Success("分配成功");
}
return ApiResponse.Error("分配失败");
}
catch (Exception ex)
{
return ApiResponse.Error($"内部错误, {ex.Message}");
}
}
public async Task<ApiResponse> AssignmentToStudentsAsync(AssigExamToStudentsDto examToStudentsDto)
{
try
{
var assignment = await _unitOfWork.GetRepository<Exam>().GetFirstOrDefaultAsync(predicate: a => a.Id == examToStudentsDto.ExamId);
if (assignment == null)
{
return ApiResponse.Error("获取失败");
}
if (assignment == null) return ApiResponse.Error("没有找到该试卷");
if (examToStudentsDto.StudentIds == null || !examToStudentsDto.StudentIds.Any())
{
return ApiResponse.Error("没有选择学生");
}
foreach (var studentId in examToStudentsDto.StudentIds)
{
var subCount = await _unitOfWork.GetRepository<Submission>().GetAll(
predicate: su => su.ExamId == examToStudentsDto.ExamId && su.StudentId == studentId
).CountAsync();
var submission = assignment.ConvertToSubmission(studentId, examToStudentsDto.CreaterId, examToStudentsDto.ClassId);
submission.AttemptNumber = (byte)(subCount + 1);
await _unitOfWork.GetRepository<Submission>().InsertAsync(submission);
}
if (await _unitOfWork.SaveChangesAsync() > 0)
{
return ApiResponse.Success();
}
return ApiResponse.Error();
}
catch (Exception ex)
{
return ApiResponse.Error($"内部错误, {ex.Message}");
}
}
public async Task<ApiResponse> AssignmentToClassAsync(Guid TeacherId, Guid examId, Guid classId)
{
try
{
var classStudents = await _classService.GetClassStudentsAsync(classId);
if (!classStudents.Status) return ApiResponse.Error(classStudents.Message);
var userlist = classStudents.Result as IEnumerable<UserListDto>;
if (userlist == null || !userlist.Any()) return ApiResponse.Error("班级没有学生");
var assignment = await _unitOfWork.GetRepository<Exam>().GetFirstOrDefaultAsync(predicate: a => a.Id == examId);
if (assignment == null) return ApiResponse.Error("没有找到该试卷");
foreach (var student in userlist)
{
var subCount = await _unitOfWork.GetRepository<Submission>().GetAll(
predicate: su => su.ExamId == examId && su.StudentId == student.Id
).CountAsync();
var submission = assignment.ConvertToSubmission(student.Id, TeacherId, classId);
submission.AttemptNumber = (byte)(subCount + 1);
await _unitOfWork.GetRepository<Submission>().InsertAsync(submission);
}
if (await _unitOfWork.SaveChangesAsync() > 0)
{
return ApiResponse.Success("创建成功");
}
return ApiResponse.Error("创建失败");
}
catch (Exception ex)
{
return ApiResponse.Error($"内部错误, {ex.Message}");
}
}
public async Task<ApiResponse> GetExamSubmissionDetailInClassAsync(AssigExamToClassDto examToClassDto)
{
try
{
var submissions = await _unitOfWork.GetRepository<Submission>().GetAllAsync(predicate: s => s.ExamId == examToClassDto.examId && s.ClassId == examToClassDto.classId);
if (submissions == null || !submissions.Any()) return ApiResponse.Error("没有找到该试卷");
var result = _mapper.Map<List<SubmissionListDto>>(submissions);
return ApiResponse.Success(result: result);
}
catch (Exception ex)
{
return ApiResponse.Error($"内部错误, {ex.Message}");
}
}
public async Task<ApiResponse> GetExamTotalErrorDistributionInClassAsync(AssigExamToClassDto examToClassDto)
{
try
{
var submissions = await _unitOfWork.GetRepository<Submission>().
GetAllAsync(predicate: s => s.ExamId == examToClassDto.examId && s.ClassId == examToClassDto.classId);
if (submissions == null || !submissions.Any()) return ApiResponse.Error("没有找到该试卷");
var errorTypeDistribution = submissions
.SelectMany(s => s.SubmissionDetails)
.Where(d => d.IsCorrect == false)
.GroupBy(d => d.ExamQuestion.Type.Name)
.ToDictionary(g => g.Key, g => g.Count());
var errorLessonDistribution = submissions
.SelectMany(s => s.SubmissionDetails)
.Where(d => d.IsCorrect == false)
.Where(d => d.ExamQuestion?.Question?.Lesson?.Title != null)
.GroupBy(d => d.ExamQuestion.Question?.Lesson?.Title)
.ToDictionary(g => g.Key, g => g.Count());
var scores = submissions.Select(s => s.OverallGrade);
var result = new ExamDistributionDto(errorTypeDistribution, errorLessonDistribution, scores);
return ApiResponse.Success(result: result);
}
catch (Exception ex)
{
return ApiResponse.Error($"内部错误, {ex.Message}");
}
}
}
}

View File

@@ -0,0 +1,19 @@
using Entities.DTO;
using TechHelper.Services;
namespace TechHelper.Services.Beta
{
public interface IExamQuestionService : IBaseService<ExamQuestionDto, Guid>
{
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>Ҫ<EFBFBD><D2AA>֪ʶ<D6AA><CAB6>,<2C>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD>,<2C><><EFBFBD><EFBFBD>ѧ<EFBFBD><D1A7><EFBFBD>б<EFBFBD>
/// </summary>
/// <param name="ExamQuestioId"></param>
/// <returns></returns>
Task<ApiResponse> GetQuestionDependy(QuesitionDenpendceyRequst request);
public record QuesitionDenpendceyRequst(Guid ExamQuestioId, Guid ClassId);
public record QuestionDependecyDto (LessonDto? Lesson, IEnumerable<float?> ScoreDistribution, IEnumerable<UserListDto> ErrorStudents);
}
}

View File

@@ -0,0 +1,66 @@
using Entities.DTO;
///*
/// 创建一个新的试卷。
/// 删除一个试卷。
/// 修改一个试卷。
/// 查看试卷详情。
///
/// Teacher
/// 获取指定用户的所有试卷预览。
/// 获取试卷的所有指定
///
namespace TechHelper.Services.Beta
{
public interface IExamService : IBaseService<ExamDto, Guid>
{
///// <summary>
///// 获取指定用户的所有试卷预览。
///// </summary>
//Task<ApiResponse> GetAllExamPreviewsAsync(Guid userId);
/// <summary>
/// 创建一个新的试卷。
/// </summary>
/// <returns>创建成功的试卷ID</returns>
Task<ApiResponse> CreateExamAsync(ExamDto examDto);
/// <summary>
/// 为指定的班级指派一个试卷
/// </summary>
/// <param name="TeacherId"> 老师ID </param>
/// <param name="assignmentId"> 试卷ID </param>
/// <param name="classId"> 班级ID </param>
/// <returns></returns>
Task<ApiResponse> AssignmentToClassAsync(Guid TeacherId , Guid assignmentId, Guid classId);
/// <summary>
/// 为指定学生指派一个试卷
/// </summary>
/// <param name="assignementId"></param>
/// <param name="studentId"></param>
/// <returns></returns>
Task<ApiResponse> AssignmentToStudentsAsync(AssigExamToStudentsDto examToStudentsDto);
/// <summary>
/// 获取该试卷在指定班级指派了多少人
/// </summary>
/// <param name="examToClassDto"></param>
/// <returns></returns>
Task<ApiResponse> GetExamSubmissionDetailInClassAsync(AssigExamToClassDto examToClassDto);
Task<ApiResponse> GetExamTotalErrorDistributionInClassAsync(AssigExamToClassDto examToClassDto);
public record ExamDistributionDto(Dictionary<string, int> ErrorTypeDistribution,
Dictionary<string, int> ErrorLessonDistribution,
IEnumerable<float> ScoreDistribution);
}
}

View File

@@ -1,6 +1,7 @@
using AutoMapper;
using Entities.Contracts;
using Entities.DTO;
using Entities.DTO.Class;
using Microsoft.VisualBasic;
using SharedDATA.Api;
using TechHelper.Context;
@@ -32,7 +33,7 @@ namespace TechHelper.Server.Services
try
{
Assignment newAssi = _mapper.Map<Assignment>(assignmentDto);
Exam newAssi = _mapper.Map<Exam>(assignmentDto);
await _examRepository.AddAsync(newAssi);
@@ -117,11 +118,11 @@ namespace TechHelper.Server.Services
{
try
{
var assignment = await _unitOfWork.GetRepository<Assignment>().GetFirstOrDefaultAsync(predicate: a => a.Id == id);
var assignment = await _unitOfWork.GetRepository<Exam>().GetFirstOrDefaultAsync(predicate: a => a.Id == id);
if (assignment == null) return ApiResponse.Error("找不到该试卷");
_unitOfWork.GetRepository<Assignment>().Delete(id);
_unitOfWork.GetRepository<AssignmentQuestion>().Delete(assignment.ExamStructId);
_unitOfWork.GetRepository<Exam>().Delete(id);
_unitOfWork.GetRepository<ExamQuestion>().Delete(assignment.ExamStructId);
if (await _unitOfWork.SaveChangesAsync() > 0)
@@ -170,7 +171,7 @@ namespace TechHelper.Server.Services
var cs = cla.Result as ICollection<ClassStudent>;
cs?.ToList().ForEach(async s =>
{
var subCount = _unitOfWork.GetRepository<Submission>().GetAll(predicate: su => su.AssignmentId == assignmentId && su.StudentId == s.StudentId);
var subCount = _unitOfWork.GetRepository<Submission>().GetAll(predicate: su => su.ExamId == assignmentId && su.StudentId == s.StudentId);
var submission = assignment.ConvertToSubmission(s.StudentId, TeacherId);
submission.AttemptNumber = (byte)(subCount.Count() + 1);
@@ -199,7 +200,7 @@ namespace TechHelper.Server.Services
examToStudentsDto.StudentIds?.ForEach(async s =>
{
var subCount = _unitOfWork.GetRepository<Submission>().GetAll(predicate: su => su.AssignmentId == examToStudentsDto.AssignmentId && su.StudentId == s);
var subCount = _unitOfWork.GetRepository<Submission>().GetAll(predicate: su => su.ExamId == examToStudentsDto.AssignmentId && su.StudentId == s);
var submission = assignment.ConvertToSubmission(s, examToStudentsDto.CreaterId);
submission.AttemptNumber = (byte)(subCount.Count() + 1);
await _unitOfWork.GetRepository<Submission>().InsertAsync(submission);

View File

@@ -0,0 +1,175 @@
using AutoMapper;
using Entities.Contracts;
using Entities.DTO;
using Microsoft.EntityFrameworkCore;
using SharedDATA.Api;
using TechHelper.Services.Beta;
namespace TechHelper.Services.Beta
{
public class ExamTypeService : IExamTypeService
{
private readonly IUnitOfWork _work;
private readonly IMapper _mapper;
public ExamTypeService(IUnitOfWork work, IMapper mapper)
{
_work = work;
_mapper = mapper;
}
public async Task<ApiResponse> GetAllAsync(QueryParameter query)
{
try
{
var repository = _work.GetRepository<ExamType>();
if (query.Search != null && !string.IsNullOrWhiteSpace(query.Search))
{
var examTypes = await repository.GetPagedListAsync(
predicate: et => et.Name.Contains(query.Search) || et.Description.Contains(query.Search),
pageSize: query.PageSize,
pageIndex: query.PageIndex
);
var examTypeDtosFiltered = _mapper.Map<IEnumerable<TypeCommonDto>>(examTypes.Items);
return new ApiResponse(true, examTypeDtosFiltered);
}
else
{
var examTypes = await repository.GetPagedListAsync(
pageSize: query.PageSize,
pageIndex: query.PageIndex,
include: i => i.Include(et => et.Exams)
);
var examTypeDtos = _mapper.Map<IEnumerable<TypeCommonDto>>(examTypes.Items);
return new ApiResponse(true, examTypeDtos);
}
}
catch (Exception ex)
{
return new ApiResponse($"获取所有考试类型时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> GetAsync(Guid id)
{
try
{
var examType = await _work.GetRepository<ExamType>().GetFirstOrDefaultAsync(
predicate: et => et.Id == id,
include: i => i
.Include(et => et.Exams));
if (examType == null)
{
return new ApiResponse("考试类型未找到。");
}
var examTypeDto = _mapper.Map<ExamTypeResponseDto>(examType);
return new ApiResponse(true, examTypeDto);
}
catch (Exception ex)
{
return new ApiResponse($"获取考试类型时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> AddAsync(ExamTypeDto model)
{
try
{
// 检查是否已存在同名考试类型
var existingExamType = await _work.GetRepository<ExamType>().GetFirstOrDefaultAsync(
predicate: et => et.Name == model.Name);
if (existingExamType != null)
{
return new ApiResponse($"考试类型 '{model.Name}' 已存在。");
}
var examType = _mapper.Map<ExamType>(model);
await _work.GetRepository<ExamType>().InsertAsync(examType);
if (await _work.SaveChangesAsync() > 0)
{
return new ApiResponse(true, examType.Id);
}
return new ApiResponse("添加考试类型失败。");
}
catch (Exception ex)
{
return new ApiResponse($"添加考试类型时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> UpdateAsync(ExamTypeDto model)
{
try
{
var existingExamType = await _work.GetRepository<ExamType>().GetFirstOrDefaultAsync(
predicate: et => et.Id == model.Id);
if (existingExamType == null)
{
return new ApiResponse("考试类型未找到。");
}
// 检查是否要修改为已存在的考试类型名称(排除当前考试类型)
var examTypeWithSameName = await _work.GetRepository<ExamType>().GetFirstOrDefaultAsync(
predicate: et => et.Name == model.Name && et.Id != model.Id);
if (examTypeWithSameName != null)
{
return new ApiResponse($"考试类型名称 '{model.Name}' 已被其他考试类型使用。");
}
_mapper.Map(model, existingExamType);
_work.GetRepository<ExamType>().Update(existingExamType);
if (await _work.SaveChangesAsync() > 0)
{
var examTypeDto = _mapper.Map<ExamTypeResponseDto>(existingExamType);
return new ApiResponse(true, examTypeDto);
}
return new ApiResponse("更新考试类型失败。");
}
catch (Exception ex)
{
return new ApiResponse($"更新考试类型时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> DeleteAsync(Guid id)
{
try
{
var existingExamType = await _work.GetRepository<ExamType>().GetFirstOrDefaultAsync(
predicate: et => et.Id == id,
include: i => i.Include(et => et.Exams));
if (existingExamType == null)
{
return new ApiResponse("考试类型未找到。");
}
// 检查是否有关联的考试
if (existingExamType.Exams != null && existingExamType.Exams.Any())
{
return new ApiResponse("无法删除该考试类型,因为存在关联的考试。");
}
_work.GetRepository<ExamType>().Delete(existingExamType);
if (await _work.SaveChangesAsync() > 0)
{
return new ApiResponse(true, "考试类型删除成功。");
}
return new ApiResponse("删除考试类型失败。");
}
catch (Exception ex)
{
return new ApiResponse($"删除考试类型时发生错误: {ex.Message}");
}
}
}
}

View File

@@ -0,0 +1,9 @@
using Entities.DTO;
using TechHelper.Services;
namespace TechHelper.Services.Beta
{
public interface IExamTypeService : IBaseService<ExamTypeDto, Guid>
{
}
}

View File

@@ -0,0 +1,155 @@
using AutoMapper;
using Entities.Contracts;
using Entities.DTO;
using Microsoft.EntityFrameworkCore;
using SharedDATA.Api;
namespace TechHelper.Services.Beta
{
public class GradeService : IGradeService
{
private readonly IUnitOfWork _work;
private readonly IMapper _mapper;
public GradeService(IUnitOfWork work, IMapper mapper)
{
_work = work;
_mapper = mapper;
}
public async Task<ApiResponse> GetAllAsync(QueryParameter query)
{
try
{
var repository = _work.GetRepository<Grade>();
if (query.Search != null && !string.IsNullOrWhiteSpace(query.Search))
{
var grades = await repository.GetPagedListAsync(
predicate: g => g.GradeName.Contains(query.Search),
pageSize: query.PageSize,
pageIndex: query.PageIndex
);
var gradeDtosFiltered = _mapper.Map<IEnumerable<GradeDto>>(grades);
return new ApiResponse(true, gradeDtosFiltered);
}
else
{
var grades = await repository.GetPagedListAsync(
pageSize: query.PageSize,
pageIndex: query.PageIndex
);
var gradeDtos = _mapper.Map<IEnumerable<GradeDto>>(grades);
return new ApiResponse(true, gradeDtos);
}
}
catch (Exception ex)
{
return new ApiResponse($"获取所有年级时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> GetAsync(Guid id)
{
try
{
var grade = await _work.GetRepository<Grade>().GetFirstOrDefaultAsync(
predicate: g => g.Id == id,
include: i => i.Include(g => g.School));
if (grade == null)
{
return new ApiResponse("年级未找到。");
}
var gradeDto = _mapper.Map<GradeDto>(grade);
return new ApiResponse(true, gradeDto);
}
catch (Exception ex)
{
return new ApiResponse($"获取年级时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> AddAsync(GradeDto model)
{
try
{
// 检查是否已存在相同学校下的同名年级
var existingGrade = await _work.GetRepository<Grade>().GetFirstOrDefaultAsync(
predicate: g => g.SchoolId == model.SchoolId && g.GradeName == model.GradeName && g.GradeLevel == model.GradeLevel);
if (existingGrade != null)
{
return new ApiResponse($"在当前学校下,年级 '{model.GradeName}' 已存在。");
}
var grade = _mapper.Map<Grade>(model);
await _work.GetRepository<Grade>().InsertAsync(grade);
if (await _work.SaveChangesAsync() > 0)
{
return new ApiResponse(true, _mapper.Map<GradeDto>(grade));
}
return new ApiResponse("添加年级失败。");
}
catch (Exception ex)
{
return new ApiResponse($"添加年级时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> UpdateAsync(GradeDto model)
{
try
{
var existingGrade = await _work.GetRepository<Grade>().GetFirstOrDefaultAsync(
predicate: g => g.Id == model.Id);
if (existingGrade == null)
{
return new ApiResponse("年级未找到。");
}
_mapper.Map(model, existingGrade);
_work.GetRepository<Grade>().Update(existingGrade);
if (await _work.SaveChangesAsync() > 0)
{
return new ApiResponse(true, _mapper.Map<GradeDto>(existingGrade));
}
return new ApiResponse("更新年级失败。");
}
catch (Exception ex)
{
return new ApiResponse($"更新年级时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> DeleteAsync(Guid id)
{
try
{
var existingGrade = await _work.GetRepository<Grade>().GetFirstOrDefaultAsync(
predicate: g => g.Id == id);
if (existingGrade == null)
{
return new ApiResponse("年级未找到。");
}
_work.GetRepository<Grade>().Delete(existingGrade);
if (await _work.SaveChangesAsync() > 0)
{
return new ApiResponse(true, "年级删除成功。");
}
return new ApiResponse("删除年级失败。");
}
catch (Exception ex)
{
return new ApiResponse($"删除年级时发生错误: {ex.Message}");
}
}
}
}

View File

@@ -0,0 +1,10 @@
using Entities.DTO;
using SharedDATA.Api;
using TechHelper.Services;
namespace TechHelper.Services.Beta
{
public interface IGradeService : IBaseService<GradeDto, Guid>
{
}
}

View File

@@ -1,4 +1,6 @@
namespace TechHelper.Services
using Entities.DTO;
namespace TechHelper.Services
{
public interface IBaseService<T, TId>
{

View File

@@ -1,16 +1,17 @@
using Entities.Contracts;
using Entities.DTO;
using Entities.DTO.Class;
using System.Net;
namespace TechHelper.Services
{
public interface IClassService : IBaseService<ClassDto, Guid>
{
public Task<ApiResponse> UserRegister(UserRegistrationToClassDto user);
public Task<ApiResponse> UserRegister(RegisterUserToClassDto user);
public Task<ApiResponse> GetUserClass(Guid user); // List<Class>
public Task<ApiResponse> GetUserClassRole(Guid user); // List<UserClassRoleDto>
public Task<ApiResponse> GetClassStudents(ClassDto classDto); // Class
public Task<ApiResponse> GetGradeClasses(byte Grade); // Class
Task GetClassStudents(byte grade, byte id);
public Task GetClassStudents(byte Grade, byte Class);
}
}

View File

@@ -1,14 +0,0 @@
using Entities.DTO;
namespace TechHelper.Services
{
public interface IUserRegistrationService
{
/// <summary>
/// 注册新用户,并根据角色关联到班级。
/// </summary>
/// <param name="registrationDto">用户注册数据。</param>
/// <returns>操作结果。</returns>
Task<ApiResponse> RegisterNewUserAsync(UserForRegistrationDto registrationDto);
}
}

View File

@@ -1,12 +0,0 @@
using Entities.Contracts;
using TechHelper.Services;
namespace TechHelper.Server.Services
{
public interface IUserSerivces : IBaseService<User, Guid>
{
Task<ApiResponse> GetStudentDetailInfo(Guid userId);
Task<ApiResponse> RestoreUserRoleInformation(User user);
Task<ApiResponse> VerifyUserInformation(Guid userId);
}
}

View File

@@ -0,0 +1,10 @@
using Entities.DTO;
using TechHelper.Services;
namespace TechHelper.Services.Beta
{
public interface IKeyPointService : IBaseService<KeyPointDto, Guid>
{
Task<ApiResponse> GetKeyPointsByLessonIdAsync(Guid lessonId);
}
}

Some files were not shown because too many files have changed in this diff Show More