diff --git a/Entities/Contracts/AppMainStruct.cs b/Entities/Contracts/AppMainStruct.cs index 65b1896..6039c28 100644 --- a/Entities/Contracts/AppMainStruct.cs +++ b/Entities/Contracts/AppMainStruct.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; +using System.Reflection; using System.Text; using System.Threading.Tasks; @@ -34,9 +36,11 @@ namespace Entities.Contracts public enum DifficultyLevel : byte { + simple, easy, medium, - hard + hard, + veryHard } public enum QuestionType : byte @@ -55,47 +59,131 @@ namespace Entities.Contracts public enum SubjectAreaEnum : byte { - Unknown = 0, - Mathematics, // 数学 - Physics, // 物理 - Chemistry, // 化学 - Biology, // 生物 - History, // 历史 - Geography, // 地理 + [Display(Name = "未知", Description = "未知")] + Unknown = 0, + + [Display(Name = "数学", Description = "数")] + Mathematics, // 数学 + + [Display(Name = "物理", Description = "物")] + Physics, // 物理 + + [Display(Name = "化学", Description = "化")] + Chemistry, // 化学 + + [Display(Name = "生物", Description = "生")] + Biology, // 生物 + + [Display(Name = "历史", Description = "史")] + History, // 历史 + + [Display(Name = "地理", Description = "地")] + Geography, // 地理 + + [Display(Name = "语文", Description = "语")] Literature, // 语文/文学 - English, // 英语 - ComputerScience, // 计算机科学 + + [Display(Name = "英语", Description = "英")] + English, // 英语 + + [Display(Name = "计算机科学", Description = "计")] + ComputerScience // 计算机科学 } public enum AssignmentStructType : byte { + [Display(Name = "根节点", Description = "根")] Root, + [Display(Name = "单个问题", Description = "问")] Question, + [Display(Name = "问题组", Description = "组")] Group, + [Display(Name = "结构", Description = "结")] Struct, + [Display(Name = "子问题", Description = "子")] SubQuestion, + [Display(Name = "选项", Description = "选")] Option } - public enum ExamType : byte { - MidtermExam, // 期中 - FinalExam, // 期末 - MonthlyExam, // 月考 - WeeklyExam, // 周考 - DailyTest, // 平时测试 - AITest, // AI测试 - } + [Display(Name = "期中考试", Description = "中")] + MidtermExam, + [Display(Name = "期末考试", Description = "末")] + FinalExam, + + [Display(Name = "月考", Description = "月")] + MonthlyExam, + + [Display(Name = "周考", Description = "周")] + WeeklyExam, + + [Display(Name = "平时测试", Description = "平")] + DailyTest, + + [Display(Name = "AI测试", Description = "AI")] + AITest, + } public enum SubmissionStatus { - Pending, // 待提交/未开始 - Submitted, // 已提交 - Graded, // 已批改 - Resubmission, // 待重新提交 (如果允许) - Late, // 迟交 - Draft, // 草稿 + [Display(Name = "待提交/未开始", Description = "待")] + Pending, + + [Display(Name = "已提交", Description = "提")] + Submitted, + + [Display(Name = "已批改", Description = "批")] + Graded, + + [Display(Name = "待重新提交", Description = "重")] + Resubmission, + + [Display(Name = "迟交", Description = "迟")] + Late, + + [Display(Name = "草稿", Description = "草")] + Draft, + } + + public static class EnumExtensions + { + public static string GetDisplayName(this Enum enumValue) + { + var fieldInfo = enumValue.GetType().GetField(enumValue.ToString()); + + if (fieldInfo == null) + { + return enumValue.ToString(); + } + + var displayAttribute = fieldInfo.GetCustomAttribute(); + + if (displayAttribute != null) + { + return displayAttribute.Name; + } + + return enumValue.ToString(); + } + + public static string GetShortName(this Enum enumValue) + { + var memberInfo = enumValue.GetType().GetMember(enumValue.ToString()).FirstOrDefault(); + + if (memberInfo != null) + { + var displayAttribute = memberInfo.GetCustomAttribute(); + + if (displayAttribute != null && !string.IsNullOrEmpty(displayAttribute.Description)) + { + return displayAttribute.Description; + } + } + + return enumValue.ToString(); + } } } diff --git a/Entities/Contracts/AssignmentQuestion.cs b/Entities/Contracts/AssignmentQuestion.cs index cfbaf91..180deda 100644 --- a/Entities/Contracts/AssignmentQuestion.cs +++ b/Entities/Contracts/AssignmentQuestion.cs @@ -40,6 +40,8 @@ namespace Entities.Contracts [Column("group_state")] public AssignmentStructType StructType { get; set; } = AssignmentStructType.Question; + public QuestionType Type { get; set; } = QuestionType.Unknown; + [Column("created_at")] public DateTime CreatedAt { get; set; } diff --git a/Entities/Contracts/Global.cs b/Entities/Contracts/Global.cs new file mode 100644 index 0000000..03c5425 --- /dev/null +++ b/Entities/Contracts/Global.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Entities.Contracts +{ + [Table("global")] + public class Global + { + [Key] + [Column("id")] + public Guid Id { get; set; } = Guid.NewGuid(); + + public SubjectAreaEnum Area { get; set; } + + public string Info { get; set; } = string.Empty; + } + + +} diff --git a/Entities/Contracts/Question.cs b/Entities/Contracts/Question.cs index 7d91b6d..c824eeb 100644 --- a/Entities/Contracts/Question.cs +++ b/Entities/Contracts/Question.cs @@ -38,6 +38,7 @@ namespace Entities.Contracts [Column("subject_area")] public SubjectAreaEnum SubjectArea { get; set; } = SubjectAreaEnum.Unknown; + public string QType { get; set; } = string.Empty; [Column("options")] public string? Options { get; set; } diff --git a/Entities/Contracts/User.cs b/Entities/Contracts/User.cs index 4054383..87cfb3c 100644 --- a/Entities/Contracts/User.cs +++ b/Entities/Contracts/User.cs @@ -15,8 +15,8 @@ namespace Entities.Contracts public string? RefreshToken { get; set; } public DateTime? RefreshTokenExpiryTime { get; set; } public string? Address { get; set; } - public string? DisplayName { get; set; } - + public string? DisplayName { get; set; } + public SubjectAreaEnum SubjectArea { get; set; } = SubjectAreaEnum.Unknown; [Column("deleted")] public bool IsDeleted { get; set; } diff --git a/Entities/DTO/AssignmentQuestionDto.cs b/Entities/DTO/AssignmentQuestionDto.cs index c38774a..d76f076 100644 --- a/Entities/DTO/AssignmentQuestionDto.cs +++ b/Entities/DTO/AssignmentQuestionDto.cs @@ -17,6 +17,8 @@ namespace Entities.DTO public float Score { get; set; } = 0; public string Sequence { get; set; } = string.Empty; public bool BCorrect { get; set; } = true; + public QuestionType Type { get; set; } = QuestionType.Unknown; + public string QType { get; set; } = string.Empty; public Layout Layout { get; set; } = Layout.horizontal; public AssignmentStructType StructType { get; set; } = AssignmentStructType.Question; diff --git a/Entities/DTO/GlobalDto.cs b/Entities/DTO/GlobalDto.cs new file mode 100644 index 0000000..c018284 --- /dev/null +++ b/Entities/DTO/GlobalDto.cs @@ -0,0 +1,23 @@ +using Entities.Contracts; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Entities.DTO +{ + + public class GlobalDto + { + + public SubjectAreaEnum SubjectArea { get; set; } = SubjectAreaEnum.Unknown; + public string Data { get; set; } = string.Empty; + } + + public class QuestionDisplayTypeData + { + public string Color { get; set; } + public string DisplayName { get; set; } + } +} diff --git a/Entities/DTO/QuestionDto.cs b/Entities/DTO/QuestionDto.cs index a35ff20..fad6196 100644 --- a/Entities/DTO/QuestionDto.cs +++ b/Entities/DTO/QuestionDto.cs @@ -16,6 +16,7 @@ namespace Entities.DTO public string Title { get; set; } = string.Empty; public QuestionType Type { get; set; } = QuestionType.Unknown; + public string QType { get; set; } = string.Empty; public string? Answer { get; set; } = string.Empty; diff --git a/Entities/DTO/SubjectTypeMetadataDto.cs b/Entities/DTO/SubjectTypeMetadataDto.cs new file mode 100644 index 0000000..6847777 --- /dev/null +++ b/Entities/DTO/SubjectTypeMetadataDto.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; +using System.Collections.Generic; +using Entities.Contracts; + +namespace Entities.DTO +{ + public class SubjectTypeMetadataDto + { + public SubjectAreaEnum SubjectArea { get; set; } = SubjectAreaEnum.Unknown; + //public Dictionary Data = new Dictionary(); + + public string Data = string.Empty; + } +} diff --git a/TechHelper.Client/Helper/Helper.cs b/TechHelper.Client/Helper/Helper.cs new file mode 100644 index 0000000..f291e01 --- /dev/null +++ b/TechHelper.Client/Helper/Helper.cs @@ -0,0 +1,31 @@ +using MudBlazor; + +namespace TechHelper.Client.Helper +{ + public static class Helper + { + public static Color GetColorFromInt(int value) + { + var v = value % Enum.GetValues(typeof(Color)).Length; + switch (value) + { + case 1: + return MudBlazor.Color.Primary; + case 2: + return MudBlazor.Color.Secondary; + case 3: + return MudBlazor.Color.Success; + case 4: + return MudBlazor.Color.Info; + case 5: + return MudBlazor.Color.Warning; + case 6: + return MudBlazor.Color.Error; + case 7: + return MudBlazor.Color.Dark; + default: + return MudBlazor.Color.Default; + } + } + } +} diff --git a/TechHelper.Client/Layout/MainLayout.razor b/TechHelper.Client/Layout/MainLayout.razor index e3345db..b48d420 100644 --- a/TechHelper.Client/Layout/MainLayout.razor +++ b/TechHelper.Client/Layout/MainLayout.razor @@ -4,83 +4,67 @@ -@* - - - + + + + + + + + + application + + + + + + + + + + + + Dashboard + Exam + Billing + + Users + Security + - - - - - - - - - - - - - - + + About + + + + + Setting + - - - - @Body + + + + + + + @Body + + + + +@code { + ErrorBoundary? errorBoundary; + protected override void OnParametersSet() + { + errorBoundary?.Recover(); + } + bool _drawerOpen = true; - - - - - - - - - *@ - - - - - - - - - - - - - - -@* - - *@ - - - @Body - - - \ No newline at end of file + void DrawerToggle() + { + _drawerOpen = !_drawerOpen; + } +} \ No newline at end of file diff --git a/TechHelper.Client/Pages/Common/Exam/AssignmentInfoCard.razor b/TechHelper.Client/Pages/Common/Exam/AssignmentInfoCard.razor index f70f9f0..763cacd 100644 --- a/TechHelper.Client/Pages/Common/Exam/AssignmentInfoCard.razor +++ b/TechHelper.Client/Pages/Common/Exam/AssignmentInfoCard.razor @@ -4,7 +4,7 @@ - 期中测试BETA版本 + BETA版本 75 @@ -12,13 +12,13 @@ - TotalNumber: + 总数: 15 - TotalScore: + 总分: 15 @@ -26,8 +26,8 @@ - - 中位数: + + 中位: 15 @@ -67,17 +67,17 @@ 类型分布 课时分布 - 成绩趋势 - 分值区间 - Success - Warning - Error - Dark +@* 成绩趋势 + 分值区间 + Success + Warning + Error + Dark *@ @code { public double[] data = { 25, 77, 28, 5 }; diff --git a/TechHelper.Client/Pages/Common/ExamGlobalInfoDialog.razor b/TechHelper.Client/Pages/Common/ExamGlobalInfoDialog.razor new file mode 100644 index 0000000..4a2ed6d --- /dev/null +++ b/TechHelper.Client/Pages/Common/ExamGlobalInfoDialog.razor @@ -0,0 +1,34 @@ +@using Entities.DTO +@inject ISnackbar Snackbar + + + + + + 编辑属性 + + + + + + + Cancel + 确认 + + + +@code { + [CascadingParameter] + private IMudDialogInstance MudDialog { get; set; } + + [Parameter] + public AssignmentDto Assignment { get; set; } = new AssignmentDto(); + + private void Cancel() => MudDialog.Cancel(); + + private void Confirm() + { + Snackbar.Add("属性已更新", Severity.Success); + MudDialog.Close(DialogResult.Ok(Assignment)); + } +} diff --git a/TechHelper.Client/Pages/Common/GlobalInfoCard.razor b/TechHelper.Client/Pages/Common/GlobalInfoCard.razor new file mode 100644 index 0000000..e1e8e1b --- /dev/null +++ b/TechHelper.Client/Pages/Common/GlobalInfoCard.razor @@ -0,0 +1,37 @@ +@using Entities.DTO +@using Entities.Contracts +@using Helper + + + + SCORE + NUMQUESTION + + + @foreach (SubjectAreaEnum item in Enum.GetValues(typeof(SubjectAreaEnum))) + { + var color = Helper.GetColorFromInt((int)item); + + + } + + DUETIME + EXAMTYPE + + + +@code { + [Parameter] + + public AssignmentDto AssignmentDto { get; set; } + [Parameter] + public string Style { get; set; } + [Parameter] + public string Height { get; set; } = "auto"; + + public void HandleQTSelectedValueChanged(SubjectAreaEnum subject) + { + AssignmentDto.SubjectArea = subject; + } +} \ No newline at end of file diff --git a/TechHelper.Client/Pages/Common/QuestionCardDialog.razor b/TechHelper.Client/Pages/Common/QuestionCardDialog.razor index ac77875..b373699 100644 --- a/TechHelper.Client/Pages/Common/QuestionCardDialog.razor +++ b/TechHelper.Client/Pages/Common/QuestionCardDialog.razor @@ -31,4 +31,4 @@ Snackbar.Add("属性已更新", Severity.Success); MudDialog.Close(DialogResult.Ok(Questions)); } -} \ No newline at end of file +} diff --git a/TechHelper.Client/Pages/Common/SimpleCard.razor b/TechHelper.Client/Pages/Common/SimpleCard.razor index b370d2b..f1ad056 100644 --- a/TechHelper.Client/Pages/Common/SimpleCard.razor +++ b/TechHelper.Client/Pages/Common/SimpleCard.razor @@ -1,4 +1,4 @@ - + @TitleContent @BodyContent @FooterContent diff --git a/TechHelper.Client/Pages/Exam/AssignmentQuestionEdit.razor b/TechHelper.Client/Pages/Exam/AssignmentQuestionEdit.razor index 86e5af7..0561315 100644 --- a/TechHelper.Client/Pages/Exam/AssignmentQuestionEdit.razor +++ b/TechHelper.Client/Pages/Exam/AssignmentQuestionEdit.razor @@ -1,5 +1,6 @@ @using Entities.DTO @using Entities.Contracts +@using Newtonsoft.Json @using TechHelper.Client.Exam @using TechHelper.Client.Pages.Exam.QuestionCard @@ -12,12 +13,30 @@ + @AssignmentStructType.Root @AssignmentStructType.Struct @AssignmentStructType.Group @AssignmentStructType.Question @AssignmentStructType.SubQuestion @AssignmentStructType.Option + + + + + @foreach (var item in QuestionTypes) + { + var qt = item; + @* Style = "@($"background - color:{ item.Value.Color} ")"*@ + + + @item.Value.DisplayName + + } + @if (AssignmentQuestion.Question != null) { @@ -30,6 +49,10 @@ [Parameter] public AssignmentQuestionDto AssignmentQuestion { get; set; } = new AssignmentQuestionDto(); public QuestionDto TempQuesdto; + Dictionary QuestionTypes = new Dictionary(); + + [Inject] + private ILocalStorageService LocalStorageService { get; set; } protected override void OnInitialized() { base.OnInitialized(); @@ -37,6 +60,30 @@ { TempQuesdto = AssignmentQuestion.Question; } + + var cs = LocalStorageService.GetItem("GlobalInfo"); + var GlobalInfo = JsonConvert.DeserializeObject>(cs); + if(GlobalInfo != null) + { + QuestionTypes = GlobalInfo; + } + } + + private void HandleQTSelectedValueChanged(string type) + { + AssignmentQuestion.QType = type; + if (AssignmentQuestion.ChildrenAssignmentQuestion.Count > 0 && AssignmentQuestion.StructType == AssignmentStructType.Group) + { + foreach (var item in AssignmentQuestion.ChildrenAssignmentQuestion) + { + item.QType = type; + if (item.Question != null) + { + item.Question.QType = type; + } + } + } + StateHasChanged(); } private void HandleSelectedValueChanged(AssignmentStructType type) diff --git a/TechHelper.Client/Pages/Exam/ExamCreate.razor b/TechHelper.Client/Pages/Exam/ExamCreate.razor index ea870a9..7dde53f 100644 --- a/TechHelper.Client/Pages/Exam/ExamCreate.razor +++ b/TechHelper.Client/Pages/Exam/ExamCreate.razor @@ -1,5 +1,7 @@ @page "/exam/create" @using AutoMapper +@using Entities.Contracts +@using Newtonsoft.Json @using TechHelper.Client.Pages.Common @using TechHelper.Client.Pages.Exam.ExamView @using TechHelper.Client.Services @@ -39,10 +41,12 @@ - 文本编辑器 - 载入 - 发布 - 指派 + 文本编辑器 + 载入 + 发布 + 指派 + Test + GlobalExamInfo @@ -84,11 +88,32 @@ private ExamParserConfig _examParserConfig { get; set; } = new ExamParserConfig(); private string EditorText = ""; + [Inject] + private ILocalStorageService LocalStorageService { get; set; } [Inject] public IMapper Mapper { get; set; } + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + + var response = await NoteService.GetNote((byte)SubjectAreaEnum.Literature); + + if (response.Status) + { + try + { + LocalStorageService.SetItem("GlobalInfo", response.Result); + } + catch (Exception ex) + { + + } + } + } + private async void OpenEditor() { var parameters = new DialogParameters { { x => x.TextEditor, _textEditor } }; @@ -169,13 +194,43 @@ [Inject] public IExamService examService { get; set; } + [Inject] + public INoteService NoteService { get; set; } + public async Task Publish() { var apiRespon = await examService.SaveParsedExam(ExamContent); Snackbar.Add(apiRespon.Message); } + public async Task OpenTest() + { + Dictionary Note = new Dictionary { { "Hello", (Color.Surface, "World") }, { "My", (Color.Surface, "App") }, }; + var json = JsonConvert.SerializeObject(Note); + var result = await NoteService.AddNote(new GlobalDto { SubjectArea = Entities.Contracts.SubjectAreaEnum.Physics, Data = json }); + + + Console.WriteLine(json); + var res = JsonConvert.DeserializeObject>(json); + + } + + private async void HandleGlobalInfo() + { + // _open = true; + // _edit = true; + // StateHasChanged(); + + var parameters = new DialogParameters { { x => x.Assignment, ExamContent } }; + + var dialog = await DialogService.ShowAsync("Exam_GlobalInfo", parameters); + var result = await dialog.Result; + if (!result.Canceled) + { + } + StateHasChanged(); + } } diff --git a/TechHelper.Client/Pages/Exam/ExamView/ExamStructView.razor b/TechHelper.Client/Pages/Exam/ExamView/ExamStructView.razor index d35d260..ea7e5aa 100644 --- a/TechHelper.Client/Pages/Exam/ExamView/ExamStructView.razor +++ b/TechHelper.Client/Pages/Exam/ExamView/ExamStructView.razor @@ -1,5 +1,6 @@ @using Entities.Contracts @using Entities.DTO +@using Newtonsoft.Json @using TechHelper.Client.Exam @using TechHelper.Client.Pages.Exam.QuestionCard @@ -22,6 +23,11 @@ @ExamStruct.StructType + @(ExamStruct.QType == string.Empty ? "" : QuestionTypes[ExamStruct.QType].DisplayName) + @if(ExamStruct.Question!=null) + { + + } @@ -75,6 +81,22 @@ [Parameter] public string Style { get; set; } = "background-color : #eeeeee"; + Dictionary QuestionTypes = new Dictionary(); + + [Inject] + private ILocalStorageService LocalStorageService { get; set; } + protected override void OnInitialized() + { + base.OnInitialized(); + + var cs = LocalStorageService.GetItem("GlobalInfo"); + var GlobalInfo = JsonConvert.DeserializeObject>(cs); + if (GlobalInfo != null) + { + QuestionTypes = GlobalInfo; + } + } + private async void HandleClick() { await ClickedStruct.InvokeAsync(ExamStruct); @@ -84,4 +106,10 @@ { await ClickedStruct.InvokeAsync(clickedChildExamStruct); } + + private void HandleSelected(int num) + { + ExamStruct.Question.DifficultyLevel = (DifficultyLevel)num; + } + } \ No newline at end of file diff --git a/TechHelper.Client/Pages/Exam/QuestionCard/QuestionEdit.razor b/TechHelper.Client/Pages/Exam/QuestionCard/QuestionEdit.razor index 0e96fce..3432676 100644 --- a/TechHelper.Client/Pages/Exam/QuestionCard/QuestionEdit.razor +++ b/TechHelper.Client/Pages/Exam/QuestionCard/QuestionEdit.razor @@ -1,10 +1,29 @@ @using Entities.DTO +@using Entities.Contracts +@using Newtonsoft.Json @using TechHelper.Client.Exam @* @Question.Id *@ 问题属性 + + + + @foreach (var item in QuestionTypes) + { + var qt = item; + @* Style = "@($"background - color:{ item.Value.Color} ")"*@ + + + @item.Value.DisplayName + + } + + @@ -15,4 +34,35 @@ @code { [Parameter] public QuestionDto Question { get; set; } = new QuestionDto(); + public int diffi = 0; + Dictionary QuestionTypes = new Dictionary(); + + [Inject] + private ILocalStorageService LocalStorageService { get; set; } + protected override void OnInitialized() + { + base.OnInitialized(); + + var cs = LocalStorageService.GetItem("GlobalInfo"); + var GlobalInfo = JsonConvert.DeserializeObject>(cs); + if (GlobalInfo != null) + { + QuestionTypes = GlobalInfo; + } + } + private void HandleSelectedValueChanged(QuestionType type) + { + Question.Type = type; + } + + private void HandleSelected(int num) + { + Question.DifficultyLevel = (DifficultyLevel)num; + } + + private void HandleQTSelectedValueChanged(string type) + { + Question.QType = type; + StateHasChanged(); + } } diff --git a/TechHelper.Client/Pages/Global/LoginInOut/LoginInOut.razor b/TechHelper.Client/Pages/Global/LoginInOut/LoginInOut.razor new file mode 100644 index 0000000..0bcd1b2 --- /dev/null +++ b/TechHelper.Client/Pages/Global/LoginInOut/LoginInOut.razor @@ -0,0 +1,32 @@ +@using Microsoft.AspNetCore.Components.WebAssembly.Authentication +@inject NavigationManager Navigation +@inject IAuthenticationClientService AuthenticationClientService + + + + + Hello, @context.User.Identity.Name! + + LOGOUT + + + Login + + + +@code { + [CascadingParameter] + private Task authenticationStateTask { get; set; } + + private async Task Logout() + { + await AuthenticationClientService.LogoutAsync(); + Navigation.NavigateTo("/"); + } + + private void LoginIN() + { + Navigation.NavigateToLogin("/login"); + } + +} \ No newline at end of file diff --git a/TechHelper.Client/Pages/Global/MainStruct/ApplicationMainIconCard.razor b/TechHelper.Client/Pages/Global/MainStruct/ApplicationMainIconCard.razor new file mode 100644 index 0000000..154a6c5 --- /dev/null +++ b/TechHelper.Client/Pages/Global/MainStruct/ApplicationMainIconCard.razor @@ -0,0 +1,11 @@ + + + TechHelper + + +@code { + [Parameter] + public string Height { get; set; } = "30px"; + [Parameter] + public string Width { get; set; } = "100%"; +} diff --git a/TechHelper.Client/Pages/Global/MainStruct/SearchBar.razor b/TechHelper.Client/Pages/Global/MainStruct/SearchBar.razor new file mode 100644 index 0000000..e0096cc --- /dev/null +++ b/TechHelper.Client/Pages/Global/MainStruct/SearchBar.razor @@ -0,0 +1,8 @@ + + + + + +@code { + public string TextValue { get; set; } +} diff --git a/TechHelper.Client/Pages/Global/MainStruct/SnackErrorBoundary.razor b/TechHelper.Client/Pages/Global/MainStruct/SnackErrorBoundary.razor new file mode 100644 index 0000000..b6c459b --- /dev/null +++ b/TechHelper.Client/Pages/Global/MainStruct/SnackErrorBoundary.razor @@ -0,0 +1,35 @@ +@inherits ErrorBoundary +@inject ISnackbar Snackbar + +@if (CurrentException is null) +{ + @ChildContent +} +else if (ErrorContent is not null) +{ + @ErrorContent(CurrentException) +} +else +{ +
+ + 组件加载或执行时出现了问题。 + + 重试 + + +
+} + + +@code { + protected override async Task OnErrorAsync(Exception exception) + { + Snackbar.Add("操作失败,请重试或联系管理员。", Severity.Error); + + await base.OnErrorAsync(exception); + } + +} diff --git a/TechHelper.Client/Pages/Home.razor b/TechHelper.Client/Pages/Home.razor index 9ae147c..4d6753f 100644 --- a/TechHelper.Client/Pages/Home.razor +++ b/TechHelper.Client/Pages/Home.razor @@ -8,9 +8,6 @@ - - - @code { [CascadingParameter] private Task authenticationStateTask { get; set; } diff --git a/TechHelper.Client/Pages/Student/BaseInfoCard/HeadIconCard.razor b/TechHelper.Client/Pages/Student/BaseInfoCard/HeadIconCard.razor new file mode 100644 index 0000000..5989da3 --- /dev/null +++ b/TechHelper.Client/Pages/Student/BaseInfoCard/HeadIconCard.razor @@ -0,0 +1,11 @@ + + + TechHelper + + +@code { + [Parameter] + public string Height { get; set; } = "250px"; + [Parameter] + public string Width { get; set; } = "100%"; +} diff --git a/TechHelper.Client/Pages/Student/BaseInfoCard/StudentSubmissionPreviewCard.razor b/TechHelper.Client/Pages/Student/BaseInfoCard/StudentSubmissionPreviewCard.razor new file mode 100644 index 0000000..adb9799 --- /dev/null +++ b/TechHelper.Client/Pages/Student/BaseInfoCard/StudentSubmissionPreviewCard.razor @@ -0,0 +1,28 @@ +@using static TechHelper.Client.Pages.Student.BaseInfoCard.StudentSubmissionPreviewTableCard + + +@if(StudentSubmission!=null) +{ + + @StudentSubmission.StudentName + @StudentSubmission.TotalProblems + @StudentSubmission.ErrorCount + @StudentSubmission.TimeSpent + @StudentSubmission.Score + +} +else +{ + + 名称 + 题目总数 + 错误总数 + 时间 + 得分 + +} +@code{ + + [Parameter] + public StudentSubmission StudentSubmission{ get; set; } +} \ No newline at end of file diff --git a/TechHelper.Client/Pages/Student/BaseInfoCard/StudentSubmissionPreviewTableCard.razor b/TechHelper.Client/Pages/Student/BaseInfoCard/StudentSubmissionPreviewTableCard.razor new file mode 100644 index 0000000..62f08da --- /dev/null +++ b/TechHelper.Client/Pages/Student/BaseInfoCard/StudentSubmissionPreviewTableCard.razor @@ -0,0 +1,39 @@ + + + + @foreach (var submission in _studentSubmissions) + { + + } + + + + +@code { + // 假设的学生提交数据模型 + public class StudentSubmission + { + public string StudentName { get; set; } + public int TotalProblems { get; set; } + public int ErrorCount { get; set; } + public TimeSpan TimeSpent { get; set; } + public int Score { get; set; } + } + + // 模拟数据列表 + private List _studentSubmissions = new(); + + protected override void OnInitialized() + { + // 模拟获取或初始化数据,实际应用中可能来自数据库或API + _studentSubmissions = new List + { + new() { StudentName = "张三", TotalProblems = 10, ErrorCount = 2, TimeSpent = TimeSpan.FromMinutes(25), Score = 80 }, + new() { StudentName = "李四", TotalProblems = 10, ErrorCount = 1, TimeSpent = TimeSpan.FromMinutes(20), Score = 90 }, + new() { StudentName = "王五", TotalProblems = 10, ErrorCount = 5, TimeSpent = TimeSpan.FromMinutes(30), Score = 50 }, + new() { StudentName = "赵六", TotalProblems = 10, ErrorCount = 3, TimeSpent = TimeSpan.FromMinutes(28), Score = 70 }, + new() { StudentName = "钱七", TotalProblems = 10, ErrorCount = 0, TimeSpent = TimeSpan.FromMinutes(18), Score = 100 } + // ... 可以添加更多模拟数据 + }; + } +} \ No newline at end of file diff --git a/TechHelper.Client/Pages/Student/BaseInfoCard/StudentSubmissionPreviewTableCard_MudCard_NoUSE.razor b/TechHelper.Client/Pages/Student/BaseInfoCard/StudentSubmissionPreviewTableCard_MudCard_NoUSE.razor new file mode 100644 index 0000000..f2063f5 --- /dev/null +++ b/TechHelper.Client/Pages/Student/BaseInfoCard/StudentSubmissionPreviewTableCard_MudCard_NoUSE.razor @@ -0,0 +1,79 @@ +@using MudBlazor +@using System.Collections.Generic + + + + + + + + + + + +
+ Hover + Dense + Striped + Bordered +
+ +@code { + // Element类定义 + public class Element + { + public int Number { get; set; } + public string Sign { get; set; } + public string Name { get; set; } + public int Position { get; set; } + public decimal Molar { get; set; } + } + + // 示例数据 + private IEnumerable Elements = new List + { + new Element { Number = 1, Sign = "H", Name = "Hydrogen", Position = 1, Molar = 1.008m }, + new Element { Number = 2, Sign = "He", Name = "Helium", Position = 0, Molar = 4.0026m }, + new Element { Number = 3, Sign = "Li", Name = "Lithium", Position = 1, Molar = 6.94m }, + new Element { Number = 4, Sign = "Be", Name = "Beryllium", Position = 2, Molar = 9.0122m }, + new Element { Number = 5, Sign = "B", Name = "Boron", Position = 13, Molar = 10.81m } + }; + + private bool _hover; + private bool _dense; + private bool _striped; + private bool _bordered; + + // 行样式函数:Position为0的行显示为斜体 + private Func _rowStyleFunc => (x, i) => + { + if (x.Position == 0) + return "font-style:italic"; + + return ""; + }; + + // 单元格样式函数:根据元素编号设置背景色,根据摩尔质量设置字体粗细 + private Func _cellStyleFunc => x => + { + string style = ""; + + if (x.Number == 1) + style += "background-color:#8CED8C"; // 浅绿色 + + else if (x.Number == 2) + style += "background-color:#E5BDE5"; // 浅紫色 + + else if (x.Number == 3) + style += "background-color:#EACE5D"; // 浅黄色 + + else if (x.Number == 4) + style += "background-color:#F1F165"; // 浅黄色 + + if (x.Molar > 5) + style += ";font-weight:bold"; + + return style; + }; +} \ No newline at end of file diff --git a/TechHelper.Client/Pages/Student/BaseInfoCard/TotalErrorQuestionType.razor b/TechHelper.Client/Pages/Student/BaseInfoCard/TotalErrorQuestionType.razor new file mode 100644 index 0000000..ba92635 --- /dev/null +++ b/TechHelper.Client/Pages/Student/BaseInfoCard/TotalErrorQuestionType.razor @@ -0,0 +1,18 @@ + + + + +@code{ + private string[] _xAxisLabels = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep" }; + private AxisChartOptions _axisChartOptions = new AxisChartOptions + { + }; + protected override void OnInitialized() + { + _axisChartOptions.MatchBoundsToSize = true; + } + private List _series = new List() + { + new ChartSeries() { Name = "United States", Data = new double[] { 40, 20, 25, 27, 46, 60, 48, 80, 15 } } + }; +} \ No newline at end of file diff --git a/TechHelper.Client/Pages/Student/HomePage.razor b/TechHelper.Client/Pages/Student/HomePage.razor index ec43a5a..d7df942 100644 --- a/TechHelper.Client/Pages/Student/HomePage.razor +++ b/TechHelper.Client/Pages/Student/HomePage.razor @@ -1,104 +1,26 @@ - +@using TechHelper.Client.Pages.Common.Exam; +@using TechHelper.Client.Pages.Student.BaseInfoCard; +@using TechHelper.Client.Pages.Common; + + + + + + + + + + + + + + - - - - - - - Total - @data.Sum().ToString() - - - - - - - - BodyContent - - - TitleContent - - - FooterContent - - - - - - BodyContent - - - TitleContent - - - FooterContent - - - - - - TitleContent - - - BodyContent - - - leran about this curson - - - - - - - - - - - Visits Summary: - - - - - - leran about this curson - - - - -@* - - Visits Summary: - - - - - - - - - - - - - - - - - - leran about this curson - - *@ - - - + - - @code { public double[] data = { 25, 77, 28, 5 }; public string[] labels = { "Oil", "Coal", "Gas", "Biomass" }; diff --git a/TechHelper.Client/Pages/Student/HomeworkCard.razor b/TechHelper.Client/Pages/Student/HomeworkCard.razor new file mode 100644 index 0000000..ee47c7e --- /dev/null +++ b/TechHelper.Client/Pages/Student/HomeworkCard.razor @@ -0,0 +1,12 @@ +@using TechHelper.Client.Pages.Common; + + + 作业 + + + 你暂时还没有任何作业 + + +@code { + +} diff --git a/TechHelper.Client/Pages/Student/NotifyCard.razor b/TechHelper.Client/Pages/Student/NotifyCard.razor new file mode 100644 index 0000000..f9deadf --- /dev/null +++ b/TechHelper.Client/Pages/Student/NotifyCard.razor @@ -0,0 +1,12 @@ +@using TechHelper.Client.Pages.Common; + + + 通知 + + + 暂时没有任何通知 + + +@code { + +} diff --git a/TechHelper.Client/Pages/Student/StudentSubmissionPreviewView.razor b/TechHelper.Client/Pages/Student/StudentSubmissionPreviewView.razor new file mode 100644 index 0000000..9b1c93e --- /dev/null +++ b/TechHelper.Client/Pages/Student/StudentSubmissionPreviewView.razor @@ -0,0 +1,11 @@ +@page "/studentSubmissionView" +@using TechHelper.Client.Pages.Student.BaseInfoCard + + + + + + + + + diff --git a/TechHelper.Client/Program.cs b/TechHelper.Client/Program.cs index 25a67a7..0a421e4 100644 --- a/TechHelper.Client/Program.cs +++ b/TechHelper.Client/Program.cs @@ -45,6 +45,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddHttpClient("WebApiClient", client => { diff --git a/TechHelper.Client/Services/INoteService.cs b/TechHelper.Client/Services/INoteService.cs new file mode 100644 index 0000000..729e29a --- /dev/null +++ b/TechHelper.Client/Services/INoteService.cs @@ -0,0 +1,14 @@ +using Entities.DTO; +using TechHelper.Services; + +namespace TechHelper.Client.Services +{ + public interface INoteService + { + public Task AddNote(GlobalDto dto); + public Task DeleteNote(byte id); + public Task GetAllNotes(); + public Task GetNote(byte id); + public Task UpdateNote(GlobalDto dto); + } +} diff --git a/TechHelper.Client/Services/NoteService.cs b/TechHelper.Client/Services/NoteService.cs new file mode 100644 index 0000000..a73e0d7 --- /dev/null +++ b/TechHelper.Client/Services/NoteService.cs @@ -0,0 +1,151 @@ +using Entities.DTO; +using System.Net.Http.Json; +using TechHelper.Client.AI; +using TechHelper.Services; + +namespace TechHelper.Client.Services +{ + public class NoteService : INoteService + { + private readonly HttpClient _client; + + public NoteService(HttpClient client) + { + _client = client; + } + + /// + /// 添加一个新笔记 + /// + /// 包含笔记数据的数据传输对象 + /// 操作结果 + public async Task AddNote(GlobalDto dto) + { + try + { + var response = await _client.PostAsJsonAsync("note", dto); + + if (response.IsSuccessStatusCode) + { + var result = await response.Content.ReadFromJsonAsync(); + return result ?? ApiResponse.Success("操作成功。"); + } + else + { + var errorContent = await response.Content.ReadAsStringAsync(); + return ApiResponse.Error($"添加失败。状态码: {response.StatusCode}。详情: {errorContent}"); + } + } + catch (HttpRequestException ex) + { + return ApiResponse.Error($"网络请求错误: {ex.Message}"); + } + } + + /// + /// 根据 ID 删除一个笔记 + /// + /// 要删除的笔记的 ID + /// 操作结果 + public async Task DeleteNote(byte id) + { + try + { + var response = await _client.DeleteAsync($"note/{id}"); + + if (response.IsSuccessStatusCode) + { + var result = await response.Content.ReadFromJsonAsync(); + return result ?? ApiResponse.Success("删除成功。"); + } + else + { + var errorContent = await response.Content.ReadAsStringAsync(); + return ApiResponse.Error($"删除失败。状态码: {response.StatusCode}。详情: {errorContent}"); + } + } + catch (HttpRequestException ex) + { + return ApiResponse.Error($"网络请求错误: {ex.Message}"); + } + } + + /// + /// 获取所有笔记 + /// + /// 包含所有笔记列表的操作结果 + public async Task GetAllNotes() + { + try + { + var response = await _client.GetAsync("note"); + + if (response.IsSuccessStatusCode) + { + var result = await response.Content.ReadFromJsonAsync(); + return result ?? ApiResponse.Success("获取成功。"); + } + else + { + var errorContent = await response.Content.ReadAsStringAsync(); + return ApiResponse.Error($"获取失败。状态码: {response.StatusCode}。详情: {errorContent}"); + } + } + catch (HttpRequestException ex) + { + return ApiResponse.Error($"网络请求错误: {ex.Message}"); + } + } + + /// + /// 根据 ID 获取单个笔记 + /// + /// 要获取的笔记的 ID + /// 包含单个笔记数据的操作结果 + public async Task GetNote(byte id) + { + try + { + var response = await _client.GetAsync($"note/{id}"); + + if (response.IsSuccessStatusCode) + { + var result = await response.Content.ReadFromJsonAsync(); + return result ?? ApiResponse.Success("获取成功。"); + } + else + { + var errorContent = await response.Content.ReadAsStringAsync(); + return ApiResponse.Error($"获取失败。状态码: {response.StatusCode}。详情: {errorContent}"); + } + } + catch (HttpRequestException ex) + { + return ApiResponse.Error($"网络请求错误: {ex.Message}"); + } + } + + public async Task UpdateNote(GlobalDto dto) + { + try + { + var response = await _client.PutAsJsonAsync("note", dto); + + if (response.IsSuccessStatusCode) + { + var result = await response.Content.ReadFromJsonAsync(); + return result ?? ApiResponse.Success("更新成功。"); + } + else + { + var errorContent = await response.Content.ReadAsStringAsync(); + return ApiResponse.Error($"更新失败。状态码: {response.StatusCode}。详情: {errorContent}"); + } + } + catch (HttpRequestException ex) + { + return ApiResponse.Error($"网络请求错误: {ex.Message}"); + } + } + } +} diff --git a/TechHelper.Client/_Imports.razor b/TechHelper.Client/_Imports.razor index fca362f..d22148d 100644 --- a/TechHelper.Client/_Imports.razor +++ b/TechHelper.Client/_Imports.razor @@ -19,4 +19,5 @@ @using TechHelper.Client.HttpRepository @using TechHelper.Client.Pages.Author @using TechHelper.Client.Pages -@using Blazored.TextEditor \ No newline at end of file +@using Blazored.TextEditor +@using TechHelper.Client.Pages.Global.MainStruct \ No newline at end of file diff --git a/TechHelper.Client/wwwroot/index.html b/TechHelper.Client/wwwroot/index.html index 01e157f..9db845f 100644 --- a/TechHelper.Client/wwwroot/index.html +++ b/TechHelper.Client/wwwroot/index.html @@ -36,6 +36,11 @@ + + diff --git a/TechHelper.Client/wwwroot/ref/Buou.png b/TechHelper.Client/wwwroot/ref/Buou.png new file mode 100644 index 0000000..36b8f3a Binary files /dev/null and b/TechHelper.Client/wwwroot/ref/Buou.png differ diff --git a/TechHelper.Client/wwwroot/ref/Caiq.png b/TechHelper.Client/wwwroot/ref/Caiq.png new file mode 100644 index 0000000..db4ecfa Binary files /dev/null and b/TechHelper.Client/wwwroot/ref/Caiq.png differ diff --git a/TechHelper.Client/wwwroot/ref/Hasq.png b/TechHelper.Client/wwwroot/ref/Hasq.png new file mode 100644 index 0000000..31bdc9f Binary files /dev/null and b/TechHelper.Client/wwwroot/ref/Hasq.png differ diff --git a/TechHelper.Client/wwwroot/ref/Keda.png b/TechHelper.Client/wwwroot/ref/Keda.png new file mode 100644 index 0000000..0e3c646 Binary files /dev/null and b/TechHelper.Client/wwwroot/ref/Keda.png differ diff --git a/TechHelper.Server/Context/ApplicationContext.cs b/TechHelper.Server/Context/ApplicationContext.cs index 5cedc4a..678c56e 100644 --- a/TechHelper.Server/Context/ApplicationContext.cs +++ b/TechHelper.Server/Context/ApplicationContext.cs @@ -21,6 +21,7 @@ namespace TechHelper.Context public DbSet Submissions { get; set; } public DbSet SubmissionDetails { get; set; } public DbSet QuestionContexts { get; set; } + public DbSet Globals { get; set; } protected override void OnModelCreating(ModelBuilder builder) { diff --git a/TechHelper.Server/Context/AutoMapperProFile.cs b/TechHelper.Server/Context/AutoMapperProFile.cs index 9cb9c2a..5a17b0f 100644 --- a/TechHelper.Server/Context/AutoMapperProFile.cs +++ b/TechHelper.Server/Context/AutoMapperProFile.cs @@ -2,6 +2,10 @@ 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; namespace TechHelper.Context { @@ -23,13 +27,13 @@ namespace TechHelper.Context public AutoMapperProFile() { CreateMap() - .ForMember(dest => dest.Id, opt => opt.Ignore()) - .ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.Name)) + .ForMember(dest => dest.Id, opt => opt.Ignore()) + .ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.Name)) .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.PasswordHash, opt => opt.Ignore()) - .ForMember(dest => dest.EmailConfirmed, opt => opt.Ignore()); + .ForMember(dest => dest.Address, opt => opt.MapFrom(src => src.HomeAddress)) + .ForMember(dest => dest.PasswordHash, opt => opt.Ignore()) + .ForMember(dest => dest.EmailConfirmed, opt => opt.Ignore()); CreateMap() .ForMember(d => d.Number, o => o.MapFrom(src => src.Class)) @@ -44,7 +48,7 @@ namespace TechHelper.Context CreateMap().ReverseMap(); - CreateMap().ReverseMap(); + CreateMap().ReverseMap(); @@ -52,7 +56,13 @@ namespace TechHelper.Context // Submission CreateMap().ReverseMap(); - CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + + + CreateMap() + .ForMember(dest => dest.Info, opt => opt.MapFrom(src => JsonConvert.SerializeObject(src.Data))); + CreateMap() + .ForMember(dest => dest.Data, opt => opt.MapFrom(src => JsonConvert.DeserializeObject>(src.Info))); } } diff --git a/TechHelper.Server/Controllers/NoteController.cs b/TechHelper.Server/Controllers/NoteController.cs new file mode 100644 index 0000000..08658d9 --- /dev/null +++ b/TechHelper.Server/Controllers/NoteController.cs @@ -0,0 +1,91 @@ +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; + } + + /// + /// 获取所有全局数据。 + /// GET: api/Note + /// + [HttpGet] + public async Task GetAll([FromQuery] QueryParameter query) + { + var response = await _noteService.GetAllAsync(query); + return Ok(response); + } + + /// + /// 根据 ID 获取单个全局数据。 + /// GET: api/Note/{id} + /// + [HttpGet("{id}")] + public async Task Get(byte id) + { + var response = await _noteService.GetAsync(id); + if (!response.Status) + { + return NotFound(response); + } + return Ok(response); + } + + /// + /// 添加新的全局数据。 + /// POST: api/Note + /// + [HttpPost] + public async Task Add([FromBody] GlobalDto model) + { + var response = await _noteService.AddAsync(model); + if (!response.Status) + { + return BadRequest(response); + } + return Ok(response); + } + + /// + /// 更新已存在的全局数据。 + /// PUT: api/Note + /// + [HttpPut] + public async Task Update([FromBody] GlobalDto model) + { + var response = await _noteService.UpdateAsync(model); + if (!response.Status) + { + return NotFound(response); + } + return Ok(response); + } + + /// + /// 根据 ID 删除全局数据。 + /// DELETE: api/Note/{id} + /// + [HttpDelete("{id}")] + public async Task Delete(byte id) + { + var response = await _noteService.DeleteAsync(id); + if (!response.Status) + { + return NotFound(response); + } + return Ok(response); + } + } +} diff --git a/TechHelper.Server/Migrations/20250901072725_question_qt_update.Designer.cs b/TechHelper.Server/Migrations/20250901072725_question_qt_update.Designer.cs new file mode 100644 index 0000000..c732281 --- /dev/null +++ b/TechHelper.Server/Migrations/20250901072725_question_qt_update.Designer.cs @@ -0,0 +1,1277 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using TechHelper.Context; + +#nullable disable + +namespace TechHelper.Server.Migrations +{ + [DbContext(typeof(ApplicationContext))] + [Migration("20250901072725_question_qt_update")] + partial class question_qt_update + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.16") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Entities.Contracts.Assignment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnName("created_at"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("created_by"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("description"); + + b.Property("DueDate") + .HasColumnType("datetime(6)") + .HasColumnName("due_date"); + + b.Property("ExamStructId") + .HasColumnType("char(36)") + .HasColumnName("exam_struct_id"); + + b.Property("ExamType") + .HasColumnType("tinyint unsigned"); + + b.Property("IsDeleted") + .HasColumnType("tinyint(1)") + .HasColumnName("deleted"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Score") + .HasColumnType("float") + .HasColumnName("score"); + + b.Property("SubjectArea") + .HasColumnType("tinyint unsigned") + .HasColumnName("subject_area"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)") + .HasColumnName("title"); + + b.Property("TotalQuestions") + .HasColumnType("tinyint unsigned") + .HasColumnName("total_points"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + b.HasIndex("ExamStructId") + .IsUnique(); + + b.HasIndex("UserId"); + + b.ToTable("assignments", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("AssignmentId") + .HasColumnType("char(36)") + .HasColumnName("assignment_id"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)") + .HasColumnName("file_name"); + + b.Property("FilePath") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)") + .HasColumnName("file_path"); + + b.Property("IsDeleted") + .HasColumnType("tinyint(1)") + .HasColumnName("deleted"); + + b.Property("UploadedAt") + .HasColumnType("datetime(6)") + .HasColumnName("uploaded_at"); + + b.HasKey("Id"); + + b.HasIndex("AssignmentId"); + + b.ToTable("assignment_attachments"); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentClass", b => + { + b.Property("AssignmentId") + .HasColumnType("char(36)") + .HasColumnName("assignment_id") + .HasColumnOrder(0); + + b.Property("ClassId") + .HasColumnType("char(36)") + .HasColumnName("class_id") + .HasColumnOrder(1); + + b.Property("AssignedAt") + .HasColumnType("datetime(6)") + .HasColumnName("assigned_at"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.HasKey("AssignmentId", "ClassId"); + + b.HasIndex("ClassId"); + + b.ToTable("assignment_class", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("AssignmentId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnName("created_at"); + + b.Property("Index") + .HasColumnType("tinyint unsigned") + .HasColumnName("question_number"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.Property("ParentAssignmentQuestionId") + .HasColumnType("char(36)") + .HasColumnName("parent_question_group_id"); + + b.Property("QuestionContextId") + .HasColumnType("char(36)") + .HasColumnName("description"); + + b.Property("QuestionId") + .HasColumnType("char(36)") + .HasColumnName("question_id"); + + b.Property("Score") + .HasColumnType("float") + .HasColumnName("score"); + + b.Property("Sequence") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("sequence"); + + b.Property("StructType") + .HasColumnType("tinyint unsigned") + .HasColumnName("group_state"); + + b.Property("Title") + .HasMaxLength(1024) + .HasColumnType("varchar(1024)") + .HasColumnName("title"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.HasKey("Id"); + + b.HasIndex("AssignmentId"); + + b.HasIndex("ParentAssignmentQuestionId"); + + b.HasIndex("QuestionContextId"); + + b.HasIndex("QuestionId"); + + b.ToTable("assignment_questions", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.Class", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)") + .HasColumnName("created_at"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CreatedAt")); + + b.Property("Description") + .HasColumnType("longtext") + .HasColumnName("description"); + + b.Property("Grade") + .HasColumnType("tinyint unsigned") + .HasColumnName("grade"); + + b.Property("HeadTeacherId") + .HasColumnType("char(36)") + .HasColumnName("head_teacher_id"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.Property("Number") + .HasColumnType("tinyint unsigned") + .HasColumnName("class"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)") + .HasColumnName("updated_at"); + + MySqlPropertyBuilderExtensions.UseMySqlComputedColumn(b.Property("UpdatedAt")); + + b.HasKey("Id"); + + b.HasIndex("HeadTeacherId"); + + b.ToTable("classes", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.ClassStudent", b => + { + b.Property("ClassId") + .HasColumnType("char(36)") + .HasColumnName("class_id") + .HasColumnOrder(0); + + b.Property("StudentId") + .HasColumnType("char(36)") + .HasColumnName("student_id") + .HasColumnOrder(1); + + b.Property("EnrollmentDate") + .HasColumnType("datetime(6)") + .HasColumnName("enrollment_date"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.HasKey("ClassId", "StudentId"); + + b.HasIndex("StudentId"); + + b.ToTable("class_student", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.ClassTeacher", b => + { + b.Property("ClassId") + .HasColumnType("char(36)") + .HasColumnName("class_id"); + + b.Property("TeacherId") + .HasColumnType("char(36)") + .HasColumnName("teacher_id"); + + b.Property("SubjectTaught") + .HasColumnType("tinyint unsigned") + .HasColumnName("subject_taught"); + + b.HasKey("ClassId", "TeacherId"); + + b.HasIndex("TeacherId"); + + b.ToTable("class_teachers", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.KeyPoint", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("LessonID") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("LessonID"); + + b.ToTable("key_point"); + }); + + modelBuilder.Entity("Entities.Contracts.Lesson", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TextbookID") + .HasColumnType("char(36)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("TextbookID"); + + b.ToTable("lesson"); + }); + + modelBuilder.Entity("Entities.Contracts.LessonQuestion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("LessonID") + .HasColumnType("char(36)"); + + b.Property("Question") + .IsRequired() + .HasMaxLength(65535) + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("LessonID"); + + b.ToTable("lesson_question"); + }); + + modelBuilder.Entity("Entities.Contracts.Question", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("Answer") + .HasMaxLength(65535) + .HasColumnType("longtext") + .HasColumnName("correct_answer"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)") + .HasColumnName("created_at"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CreatedAt")); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("created_by"); + + b.Property("DifficultyLevel") + .HasMaxLength(10) + .HasColumnType("tinyint unsigned") + .HasColumnName("difficulty_level"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.Property("KeyPointId") + .HasColumnType("char(36)") + .HasColumnName("key_point"); + + b.Property("LessonId") + .HasColumnType("char(36)") + .HasColumnName("lesson"); + + b.Property("Options") + .HasColumnType("longtext") + .HasColumnName("options"); + + b.Property("QType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SubjectArea") + .HasMaxLength(100) + .HasColumnType("tinyint unsigned") + .HasColumnName("subject_area"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(65535) + .HasColumnType("longtext") + .HasColumnName("question_text"); + + b.Property("Type") + .HasMaxLength(20) + .HasColumnType("tinyint unsigned") + .HasColumnName("question_type"); + + b.Property("UpdatedAt") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)") + .HasColumnName("updated_at"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + b.HasIndex("KeyPointId"); + + b.HasIndex("LessonId"); + + b.HasIndex("Title") + .HasAnnotation("MySql:IndexPrefixLength", new[] { 20 }); + + b.ToTable("questions", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.QuestionContext", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("QuestionContexts"); + }); + + modelBuilder.Entity("Entities.Contracts.Submission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("AssignmentId") + .HasColumnType("char(36)") + .HasColumnName("assignment_id"); + + b.Property("AttemptNumber") + .HasColumnType("tinyint unsigned") + .HasColumnName("attempt_number"); + + b.Property("ErrorQuesNum") + .HasColumnType("tinyint unsigned"); + + b.Property("GradedAt") + .HasColumnType("datetime(6)") + .HasColumnName("graded_at"); + + b.Property("GraderId") + .HasColumnType("char(36)") + .HasColumnName("graded_by"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.Property("OverallFeedback") + .HasColumnType("longtext") + .HasColumnName("overall_feedback"); + + b.Property("OverallGrade") + .HasPrecision(5, 2) + .HasColumnType("float") + .HasColumnName("overall_grade"); + + b.Property("Status") + .HasMaxLength(15) + .HasColumnType("int") + .HasColumnName("status"); + + b.Property("StudentId") + .HasColumnType("char(36)") + .HasColumnName("student_id"); + + b.Property("SubmissionTime") + .HasColumnType("datetime(6)") + .HasColumnName("submission_time"); + + b.Property("TotalQuesNum") + .HasColumnType("tinyint unsigned"); + + b.Property("TotalScore") + .HasColumnType("tinyint unsigned"); + + b.HasKey("Id"); + + b.HasIndex("AssignmentId"); + + b.HasIndex("GraderId"); + + b.HasIndex("StudentId"); + + b.ToTable("submissions", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.SubmissionDetail", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("AssignmentQuestionId") + .HasColumnType("char(36)") + .HasColumnName("assignment_question_id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)") + .HasColumnName("created_at"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CreatedAt")); + + b.Property("IsCorrect") + .HasColumnType("tinyint(1)") + .HasColumnName("is_correct"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.Property("PointsAwarded") + .HasPrecision(5, 2) + .HasColumnType("float") + .HasColumnName("points_awarded"); + + b.Property("Status") + .HasColumnType("int") + .HasColumnName("status"); + + b.Property("StudentAnswer") + .HasColumnType("longtext") + .HasColumnName("student_answer"); + + b.Property("StudentId") + .HasColumnType("char(36)") + .HasColumnName("student_id"); + + b.Property("SubmissionId") + .HasColumnType("char(36)") + .HasColumnName("submission_id"); + + b.Property("TeacherFeedback") + .HasColumnType("longtext") + .HasColumnName("teacher_feedback"); + + b.Property("UpdatedAt") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)") + .HasColumnName("updated_at"); + + b.HasKey("Id"); + + b.HasIndex("AssignmentQuestionId"); + + b.HasIndex("StudentId"); + + b.HasIndex("SubmissionId"); + + b.ToTable("submission_details", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.Textbook", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Grade") + .HasColumnType("tinyint unsigned"); + + b.Property("Publisher") + .HasColumnType("tinyint unsigned"); + + b.Property("SubjectArea") + .HasColumnType("tinyint unsigned"); + + b.Property("Title") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("textbook"); + }); + + modelBuilder.Entity("Entities.Contracts.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Address") + .HasColumnType("longtext"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("DisplayName") + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeleted") + .HasColumnType("tinyint(1)") + .HasColumnName("deleted"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("RefreshToken") + .HasColumnType("longtext"); + + b.Property("RefreshTokenExpiryTime") + .HasColumnType("datetime(6)"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + + b.HasData( + new + { + Id = new Guid("94f0d8d9-ffba-4e28-b578-8596363d42ae"), + Name = "Student", + NormalizedName = "STUDENT" + }, + new + { + Id = new Guid("67de6514-79a5-4a9c-b54c-13cac296b0c6"), + Name = "Teacher", + NormalizedName = "TEACHER" + }, + new + { + Id = new Guid("bf46ed67-2dc9-40f8-8717-37dd3572f274"), + Name = "Administrator", + NormalizedName = "ADMINISTRATOR" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.Assignment", b => + { + b.HasOne("Entities.Contracts.User", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.AssignmentQuestion", "ExamStruct") + .WithOne() + .HasForeignKey("Entities.Contracts.Assignment", "ExamStructId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", null) + .WithMany("CreatedAssignments") + .HasForeignKey("UserId"); + + b.Navigation("Creator"); + + b.Navigation("ExamStruct"); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentAttachment", b => + { + b.HasOne("Entities.Contracts.Assignment", "Assignment") + .WithMany("AssignmentAttachments") + .HasForeignKey("AssignmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Assignment"); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentClass", b => + { + b.HasOne("Entities.Contracts.Assignment", "Assignment") + .WithMany("AssignmentClasses") + .HasForeignKey("AssignmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.Class", "Class") + .WithMany("AssignmentClasses") + .HasForeignKey("ClassId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Assignment"); + + b.Navigation("Class"); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b => + { + b.HasOne("Entities.Contracts.Assignment", "Assignment") + .WithMany() + .HasForeignKey("AssignmentId"); + + b.HasOne("Entities.Contracts.AssignmentQuestion", "ParentAssignmentQuestion") + .WithMany("ChildrenAssignmentQuestion") + .HasForeignKey("ParentAssignmentQuestionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Entities.Contracts.QuestionContext", "QuestionContext") + .WithMany("Questions") + .HasForeignKey("QuestionContextId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Entities.Contracts.Question", "Question") + .WithMany("AssignmentQuestions") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Assignment"); + + b.Navigation("ParentAssignmentQuestion"); + + b.Navigation("Question"); + + b.Navigation("QuestionContext"); + }); + + modelBuilder.Entity("Entities.Contracts.Class", b => + { + b.HasOne("Entities.Contracts.User", "HeadTeacher") + .WithMany() + .HasForeignKey("HeadTeacherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("HeadTeacher"); + }); + + modelBuilder.Entity("Entities.Contracts.ClassStudent", b => + { + b.HasOne("Entities.Contracts.Class", "Class") + .WithMany("ClassStudents") + .HasForeignKey("ClassId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", "Student") + .WithMany("EnrolledClassesLink") + .HasForeignKey("StudentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Class"); + + b.Navigation("Student"); + }); + + modelBuilder.Entity("Entities.Contracts.ClassTeacher", b => + { + b.HasOne("Entities.Contracts.Class", "Class") + .WithMany("ClassTeachers") + .HasForeignKey("ClassId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", "Teacher") + .WithMany("TaughtClassesLink") + .HasForeignKey("TeacherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Class"); + + b.Navigation("Teacher"); + }); + + modelBuilder.Entity("Entities.Contracts.KeyPoint", b => + { + b.HasOne("Entities.Contracts.Lesson", "Lesson") + .WithMany("KeyPoints") + .HasForeignKey("LessonID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Lesson"); + }); + + modelBuilder.Entity("Entities.Contracts.Lesson", b => + { + b.HasOne("Entities.Contracts.Textbook", "Textbook") + .WithMany("Lessons") + .HasForeignKey("TextbookID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Textbook"); + }); + + modelBuilder.Entity("Entities.Contracts.LessonQuestion", b => + { + b.HasOne("Entities.Contracts.Lesson", "Lesson") + .WithMany("LessonQuestions") + .HasForeignKey("LessonID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Lesson"); + }); + + modelBuilder.Entity("Entities.Contracts.Question", b => + { + b.HasOne("Entities.Contracts.User", "Creator") + .WithMany("CreatedQuestions") + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Entities.Contracts.KeyPoint", "KeyPoint") + .WithMany("Questions") + .HasForeignKey("KeyPointId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Entities.Contracts.Lesson", "Lesson") + .WithMany("Questions") + .HasForeignKey("LessonId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Creator"); + + b.Navigation("KeyPoint"); + + b.Navigation("Lesson"); + }); + + modelBuilder.Entity("Entities.Contracts.Submission", b => + { + b.HasOne("Entities.Contracts.Assignment", "Assignment") + .WithMany("Submissions") + .HasForeignKey("AssignmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", "Grader") + .WithMany("GradedSubmissions") + .HasForeignKey("GraderId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Entities.Contracts.User", "Student") + .WithMany("SubmissionsAsStudent") + .HasForeignKey("StudentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Assignment"); + + b.Navigation("Grader"); + + b.Navigation("Student"); + }); + + modelBuilder.Entity("Entities.Contracts.SubmissionDetail", b => + { + b.HasOne("Entities.Contracts.AssignmentQuestion", "AssignmentQuestion") + .WithMany("SubmissionDetails") + .HasForeignKey("AssignmentQuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", "Student") + .WithMany("SubmissionDetails") + .HasForeignKey("StudentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.Submission", "Submission") + .WithMany("SubmissionDetails") + .HasForeignKey("SubmissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AssignmentQuestion"); + + b.Navigation("Student"); + + b.Navigation("Submission"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Entities.Contracts.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Entities.Contracts.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Entities.Contracts.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Entities.Contracts.Assignment", b => + { + b.Navigation("AssignmentAttachments"); + + b.Navigation("AssignmentClasses"); + + b.Navigation("Submissions"); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b => + { + b.Navigation("ChildrenAssignmentQuestion"); + + b.Navigation("SubmissionDetails"); + }); + + modelBuilder.Entity("Entities.Contracts.Class", b => + { + b.Navigation("AssignmentClasses"); + + b.Navigation("ClassStudents"); + + b.Navigation("ClassTeachers"); + }); + + modelBuilder.Entity("Entities.Contracts.KeyPoint", b => + { + b.Navigation("Questions"); + }); + + modelBuilder.Entity("Entities.Contracts.Lesson", b => + { + b.Navigation("KeyPoints"); + + b.Navigation("LessonQuestions"); + + b.Navigation("Questions"); + }); + + modelBuilder.Entity("Entities.Contracts.Question", b => + { + b.Navigation("AssignmentQuestions"); + }); + + modelBuilder.Entity("Entities.Contracts.QuestionContext", b => + { + b.Navigation("Questions"); + }); + + modelBuilder.Entity("Entities.Contracts.Submission", b => + { + b.Navigation("SubmissionDetails"); + }); + + modelBuilder.Entity("Entities.Contracts.Textbook", b => + { + b.Navigation("Lessons"); + }); + + modelBuilder.Entity("Entities.Contracts.User", b => + { + b.Navigation("CreatedAssignments"); + + b.Navigation("CreatedQuestions"); + + b.Navigation("EnrolledClassesLink"); + + b.Navigation("GradedSubmissions"); + + b.Navigation("SubmissionDetails"); + + b.Navigation("SubmissionsAsStudent"); + + b.Navigation("TaughtClassesLink"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/TechHelper.Server/Migrations/20250901072725_question_qt_update.cs b/TechHelper.Server/Migrations/20250901072725_question_qt_update.cs new file mode 100644 index 0000000..fc93975 --- /dev/null +++ b/TechHelper.Server/Migrations/20250901072725_question_qt_update.cs @@ -0,0 +1,93 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace TechHelper.Server.Migrations +{ + /// + public partial class question_qt_update : Migration + { + /// + 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( + name: "QType", + table: "questions", + type: "longtext", + nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + 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" } + }); + } + + /// + 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" } + }); + } + } +} diff --git a/TechHelper.Server/Migrations/20250901080732_question_qt_update_2.Designer.cs b/TechHelper.Server/Migrations/20250901080732_question_qt_update_2.Designer.cs new file mode 100644 index 0000000..769e685 --- /dev/null +++ b/TechHelper.Server/Migrations/20250901080732_question_qt_update_2.Designer.cs @@ -0,0 +1,1296 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using TechHelper.Context; + +#nullable disable + +namespace TechHelper.Server.Migrations +{ + [DbContext(typeof(ApplicationContext))] + [Migration("20250901080732_question_qt_update_2")] + partial class question_qt_update_2 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.16") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Entities.Contracts.Assignment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnName("created_at"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("created_by"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("description"); + + b.Property("DueDate") + .HasColumnType("datetime(6)") + .HasColumnName("due_date"); + + b.Property("ExamStructId") + .HasColumnType("char(36)") + .HasColumnName("exam_struct_id"); + + b.Property("ExamType") + .HasColumnType("tinyint unsigned"); + + b.Property("IsDeleted") + .HasColumnType("tinyint(1)") + .HasColumnName("deleted"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Score") + .HasColumnType("float") + .HasColumnName("score"); + + b.Property("SubjectArea") + .HasColumnType("tinyint unsigned") + .HasColumnName("subject_area"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)") + .HasColumnName("title"); + + b.Property("TotalQuestions") + .HasColumnType("tinyint unsigned") + .HasColumnName("total_points"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + b.HasIndex("ExamStructId") + .IsUnique(); + + b.HasIndex("UserId"); + + b.ToTable("assignments", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("AssignmentId") + .HasColumnType("char(36)") + .HasColumnName("assignment_id"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)") + .HasColumnName("file_name"); + + b.Property("FilePath") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)") + .HasColumnName("file_path"); + + b.Property("IsDeleted") + .HasColumnType("tinyint(1)") + .HasColumnName("deleted"); + + b.Property("UploadedAt") + .HasColumnType("datetime(6)") + .HasColumnName("uploaded_at"); + + b.HasKey("Id"); + + b.HasIndex("AssignmentId"); + + b.ToTable("assignment_attachments"); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentClass", b => + { + b.Property("AssignmentId") + .HasColumnType("char(36)") + .HasColumnName("assignment_id") + .HasColumnOrder(0); + + b.Property("ClassId") + .HasColumnType("char(36)") + .HasColumnName("class_id") + .HasColumnOrder(1); + + b.Property("AssignedAt") + .HasColumnType("datetime(6)") + .HasColumnName("assigned_at"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.HasKey("AssignmentId", "ClassId"); + + b.HasIndex("ClassId"); + + b.ToTable("assignment_class", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("AssignmentId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnName("created_at"); + + b.Property("Index") + .HasColumnType("tinyint unsigned") + .HasColumnName("question_number"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.Property("ParentAssignmentQuestionId") + .HasColumnType("char(36)") + .HasColumnName("parent_question_group_id"); + + b.Property("QuestionContextId") + .HasColumnType("char(36)") + .HasColumnName("description"); + + b.Property("QuestionId") + .HasColumnType("char(36)") + .HasColumnName("question_id"); + + b.Property("Score") + .HasColumnType("float") + .HasColumnName("score"); + + b.Property("Sequence") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("sequence"); + + b.Property("StructType") + .HasColumnType("tinyint unsigned") + .HasColumnName("group_state"); + + b.Property("Title") + .HasMaxLength(1024) + .HasColumnType("varchar(1024)") + .HasColumnName("title"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.HasKey("Id"); + + b.HasIndex("AssignmentId"); + + b.HasIndex("ParentAssignmentQuestionId"); + + b.HasIndex("QuestionContextId"); + + b.HasIndex("QuestionId"); + + b.ToTable("assignment_questions", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.Class", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)") + .HasColumnName("created_at"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CreatedAt")); + + b.Property("Description") + .HasColumnType("longtext") + .HasColumnName("description"); + + b.Property("Grade") + .HasColumnType("tinyint unsigned") + .HasColumnName("grade"); + + b.Property("HeadTeacherId") + .HasColumnType("char(36)") + .HasColumnName("head_teacher_id"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.Property("Number") + .HasColumnType("tinyint unsigned") + .HasColumnName("class"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)") + .HasColumnName("updated_at"); + + MySqlPropertyBuilderExtensions.UseMySqlComputedColumn(b.Property("UpdatedAt")); + + b.HasKey("Id"); + + b.HasIndex("HeadTeacherId"); + + b.ToTable("classes", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.ClassStudent", b => + { + b.Property("ClassId") + .HasColumnType("char(36)") + .HasColumnName("class_id") + .HasColumnOrder(0); + + b.Property("StudentId") + .HasColumnType("char(36)") + .HasColumnName("student_id") + .HasColumnOrder(1); + + b.Property("EnrollmentDate") + .HasColumnType("datetime(6)") + .HasColumnName("enrollment_date"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.HasKey("ClassId", "StudentId"); + + b.HasIndex("StudentId"); + + b.ToTable("class_student", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.ClassTeacher", b => + { + b.Property("ClassId") + .HasColumnType("char(36)") + .HasColumnName("class_id"); + + b.Property("TeacherId") + .HasColumnType("char(36)") + .HasColumnName("teacher_id"); + + b.Property("SubjectTaught") + .HasColumnType("tinyint unsigned") + .HasColumnName("subject_taught"); + + b.HasKey("ClassId", "TeacherId"); + + b.HasIndex("TeacherId"); + + b.ToTable("class_teachers", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.Global", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("Area") + .HasColumnType("tinyint unsigned"); + + b.Property("Info") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("global"); + }); + + modelBuilder.Entity("Entities.Contracts.KeyPoint", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("LessonID") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("LessonID"); + + b.ToTable("key_point"); + }); + + modelBuilder.Entity("Entities.Contracts.Lesson", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TextbookID") + .HasColumnType("char(36)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("TextbookID"); + + b.ToTable("lesson"); + }); + + modelBuilder.Entity("Entities.Contracts.LessonQuestion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("LessonID") + .HasColumnType("char(36)"); + + b.Property("Question") + .IsRequired() + .HasMaxLength(65535) + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("LessonID"); + + b.ToTable("lesson_question"); + }); + + modelBuilder.Entity("Entities.Contracts.Question", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("Answer") + .HasMaxLength(65535) + .HasColumnType("longtext") + .HasColumnName("correct_answer"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)") + .HasColumnName("created_at"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CreatedAt")); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("created_by"); + + b.Property("DifficultyLevel") + .HasMaxLength(10) + .HasColumnType("tinyint unsigned") + .HasColumnName("difficulty_level"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.Property("KeyPointId") + .HasColumnType("char(36)") + .HasColumnName("key_point"); + + b.Property("LessonId") + .HasColumnType("char(36)") + .HasColumnName("lesson"); + + b.Property("Options") + .HasColumnType("longtext") + .HasColumnName("options"); + + b.Property("QType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SubjectArea") + .HasMaxLength(100) + .HasColumnType("tinyint unsigned") + .HasColumnName("subject_area"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(65535) + .HasColumnType("longtext") + .HasColumnName("question_text"); + + b.Property("Type") + .HasMaxLength(20) + .HasColumnType("tinyint unsigned") + .HasColumnName("question_type"); + + b.Property("UpdatedAt") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)") + .HasColumnName("updated_at"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + b.HasIndex("KeyPointId"); + + b.HasIndex("LessonId"); + + b.HasIndex("Title") + .HasAnnotation("MySql:IndexPrefixLength", new[] { 20 }); + + b.ToTable("questions", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.QuestionContext", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("QuestionContexts"); + }); + + modelBuilder.Entity("Entities.Contracts.Submission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("AssignmentId") + .HasColumnType("char(36)") + .HasColumnName("assignment_id"); + + b.Property("AttemptNumber") + .HasColumnType("tinyint unsigned") + .HasColumnName("attempt_number"); + + b.Property("ErrorQuesNum") + .HasColumnType("tinyint unsigned"); + + b.Property("GradedAt") + .HasColumnType("datetime(6)") + .HasColumnName("graded_at"); + + b.Property("GraderId") + .HasColumnType("char(36)") + .HasColumnName("graded_by"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.Property("OverallFeedback") + .HasColumnType("longtext") + .HasColumnName("overall_feedback"); + + b.Property("OverallGrade") + .HasPrecision(5, 2) + .HasColumnType("float") + .HasColumnName("overall_grade"); + + b.Property("Status") + .HasMaxLength(15) + .HasColumnType("int") + .HasColumnName("status"); + + b.Property("StudentId") + .HasColumnType("char(36)") + .HasColumnName("student_id"); + + b.Property("SubmissionTime") + .HasColumnType("datetime(6)") + .HasColumnName("submission_time"); + + b.Property("TotalQuesNum") + .HasColumnType("tinyint unsigned"); + + b.Property("TotalScore") + .HasColumnType("tinyint unsigned"); + + b.HasKey("Id"); + + b.HasIndex("AssignmentId"); + + b.HasIndex("GraderId"); + + b.HasIndex("StudentId"); + + b.ToTable("submissions", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.SubmissionDetail", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("AssignmentQuestionId") + .HasColumnType("char(36)") + .HasColumnName("assignment_question_id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)") + .HasColumnName("created_at"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CreatedAt")); + + b.Property("IsCorrect") + .HasColumnType("tinyint(1)") + .HasColumnName("is_correct"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.Property("PointsAwarded") + .HasPrecision(5, 2) + .HasColumnType("float") + .HasColumnName("points_awarded"); + + b.Property("Status") + .HasColumnType("int") + .HasColumnName("status"); + + b.Property("StudentAnswer") + .HasColumnType("longtext") + .HasColumnName("student_answer"); + + b.Property("StudentId") + .HasColumnType("char(36)") + .HasColumnName("student_id"); + + b.Property("SubmissionId") + .HasColumnType("char(36)") + .HasColumnName("submission_id"); + + b.Property("TeacherFeedback") + .HasColumnType("longtext") + .HasColumnName("teacher_feedback"); + + b.Property("UpdatedAt") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)") + .HasColumnName("updated_at"); + + b.HasKey("Id"); + + b.HasIndex("AssignmentQuestionId"); + + b.HasIndex("StudentId"); + + b.HasIndex("SubmissionId"); + + b.ToTable("submission_details", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.Textbook", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Grade") + .HasColumnType("tinyint unsigned"); + + b.Property("Publisher") + .HasColumnType("tinyint unsigned"); + + b.Property("SubjectArea") + .HasColumnType("tinyint unsigned"); + + b.Property("Title") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("textbook"); + }); + + modelBuilder.Entity("Entities.Contracts.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Address") + .HasColumnType("longtext"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("DisplayName") + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeleted") + .HasColumnType("tinyint(1)") + .HasColumnName("deleted"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("RefreshToken") + .HasColumnType("longtext"); + + b.Property("RefreshTokenExpiryTime") + .HasColumnType("datetime(6)"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + + b.HasData( + new + { + Id = new Guid("5c7a7971-2610-4bce-9e41-0caffd5a5558"), + Name = "Student", + NormalizedName = "STUDENT" + }, + new + { + Id = new Guid("49854839-b861-4d42-bdbe-96b1a66c25ef"), + Name = "Teacher", + NormalizedName = "TEACHER" + }, + new + { + Id = new Guid("83ff7de8-edc9-47f8-8de8-22f892ca6bb5"), + Name = "Administrator", + NormalizedName = "ADMINISTRATOR" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.Assignment", b => + { + b.HasOne("Entities.Contracts.User", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.AssignmentQuestion", "ExamStruct") + .WithOne() + .HasForeignKey("Entities.Contracts.Assignment", "ExamStructId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", null) + .WithMany("CreatedAssignments") + .HasForeignKey("UserId"); + + b.Navigation("Creator"); + + b.Navigation("ExamStruct"); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentAttachment", b => + { + b.HasOne("Entities.Contracts.Assignment", "Assignment") + .WithMany("AssignmentAttachments") + .HasForeignKey("AssignmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Assignment"); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentClass", b => + { + b.HasOne("Entities.Contracts.Assignment", "Assignment") + .WithMany("AssignmentClasses") + .HasForeignKey("AssignmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.Class", "Class") + .WithMany("AssignmentClasses") + .HasForeignKey("ClassId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Assignment"); + + b.Navigation("Class"); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b => + { + b.HasOne("Entities.Contracts.Assignment", "Assignment") + .WithMany() + .HasForeignKey("AssignmentId"); + + b.HasOne("Entities.Contracts.AssignmentQuestion", "ParentAssignmentQuestion") + .WithMany("ChildrenAssignmentQuestion") + .HasForeignKey("ParentAssignmentQuestionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Entities.Contracts.QuestionContext", "QuestionContext") + .WithMany("Questions") + .HasForeignKey("QuestionContextId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Entities.Contracts.Question", "Question") + .WithMany("AssignmentQuestions") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Assignment"); + + b.Navigation("ParentAssignmentQuestion"); + + b.Navigation("Question"); + + b.Navigation("QuestionContext"); + }); + + modelBuilder.Entity("Entities.Contracts.Class", b => + { + b.HasOne("Entities.Contracts.User", "HeadTeacher") + .WithMany() + .HasForeignKey("HeadTeacherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("HeadTeacher"); + }); + + modelBuilder.Entity("Entities.Contracts.ClassStudent", b => + { + b.HasOne("Entities.Contracts.Class", "Class") + .WithMany("ClassStudents") + .HasForeignKey("ClassId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", "Student") + .WithMany("EnrolledClassesLink") + .HasForeignKey("StudentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Class"); + + b.Navigation("Student"); + }); + + modelBuilder.Entity("Entities.Contracts.ClassTeacher", b => + { + b.HasOne("Entities.Contracts.Class", "Class") + .WithMany("ClassTeachers") + .HasForeignKey("ClassId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", "Teacher") + .WithMany("TaughtClassesLink") + .HasForeignKey("TeacherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Class"); + + b.Navigation("Teacher"); + }); + + modelBuilder.Entity("Entities.Contracts.KeyPoint", b => + { + b.HasOne("Entities.Contracts.Lesson", "Lesson") + .WithMany("KeyPoints") + .HasForeignKey("LessonID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Lesson"); + }); + + modelBuilder.Entity("Entities.Contracts.Lesson", b => + { + b.HasOne("Entities.Contracts.Textbook", "Textbook") + .WithMany("Lessons") + .HasForeignKey("TextbookID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Textbook"); + }); + + modelBuilder.Entity("Entities.Contracts.LessonQuestion", b => + { + b.HasOne("Entities.Contracts.Lesson", "Lesson") + .WithMany("LessonQuestions") + .HasForeignKey("LessonID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Lesson"); + }); + + modelBuilder.Entity("Entities.Contracts.Question", b => + { + b.HasOne("Entities.Contracts.User", "Creator") + .WithMany("CreatedQuestions") + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Entities.Contracts.KeyPoint", "KeyPoint") + .WithMany("Questions") + .HasForeignKey("KeyPointId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Entities.Contracts.Lesson", "Lesson") + .WithMany("Questions") + .HasForeignKey("LessonId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Creator"); + + b.Navigation("KeyPoint"); + + b.Navigation("Lesson"); + }); + + modelBuilder.Entity("Entities.Contracts.Submission", b => + { + b.HasOne("Entities.Contracts.Assignment", "Assignment") + .WithMany("Submissions") + .HasForeignKey("AssignmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", "Grader") + .WithMany("GradedSubmissions") + .HasForeignKey("GraderId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Entities.Contracts.User", "Student") + .WithMany("SubmissionsAsStudent") + .HasForeignKey("StudentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Assignment"); + + b.Navigation("Grader"); + + b.Navigation("Student"); + }); + + modelBuilder.Entity("Entities.Contracts.SubmissionDetail", b => + { + b.HasOne("Entities.Contracts.AssignmentQuestion", "AssignmentQuestion") + .WithMany("SubmissionDetails") + .HasForeignKey("AssignmentQuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", "Student") + .WithMany("SubmissionDetails") + .HasForeignKey("StudentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.Submission", "Submission") + .WithMany("SubmissionDetails") + .HasForeignKey("SubmissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AssignmentQuestion"); + + b.Navigation("Student"); + + b.Navigation("Submission"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Entities.Contracts.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Entities.Contracts.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Entities.Contracts.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Entities.Contracts.Assignment", b => + { + b.Navigation("AssignmentAttachments"); + + b.Navigation("AssignmentClasses"); + + b.Navigation("Submissions"); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b => + { + b.Navigation("ChildrenAssignmentQuestion"); + + b.Navigation("SubmissionDetails"); + }); + + modelBuilder.Entity("Entities.Contracts.Class", b => + { + b.Navigation("AssignmentClasses"); + + b.Navigation("ClassStudents"); + + b.Navigation("ClassTeachers"); + }); + + modelBuilder.Entity("Entities.Contracts.KeyPoint", b => + { + b.Navigation("Questions"); + }); + + modelBuilder.Entity("Entities.Contracts.Lesson", b => + { + b.Navigation("KeyPoints"); + + b.Navigation("LessonQuestions"); + + b.Navigation("Questions"); + }); + + modelBuilder.Entity("Entities.Contracts.Question", b => + { + b.Navigation("AssignmentQuestions"); + }); + + modelBuilder.Entity("Entities.Contracts.QuestionContext", b => + { + b.Navigation("Questions"); + }); + + modelBuilder.Entity("Entities.Contracts.Submission", b => + { + b.Navigation("SubmissionDetails"); + }); + + modelBuilder.Entity("Entities.Contracts.Textbook", b => + { + b.Navigation("Lessons"); + }); + + modelBuilder.Entity("Entities.Contracts.User", b => + { + b.Navigation("CreatedAssignments"); + + b.Navigation("CreatedQuestions"); + + b.Navigation("EnrolledClassesLink"); + + b.Navigation("GradedSubmissions"); + + b.Navigation("SubmissionDetails"); + + b.Navigation("SubmissionsAsStudent"); + + b.Navigation("TaughtClassesLink"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/TechHelper.Server/Migrations/20250901080732_question_qt_update_2.cs b/TechHelper.Server/Migrations/20250901080732_question_qt_update_2.cs new file mode 100644 index 0000000..2603b32 --- /dev/null +++ b/TechHelper.Server/Migrations/20250901080732_question_qt_update_2.cs @@ -0,0 +1,89 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace TechHelper.Server.Migrations +{ + /// + public partial class question_qt_update_2 : Migration + { + /// + 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(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Area = table.Column(type: "tinyint unsigned", nullable: false), + Info = table.Column(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" } + }); + } + + /// + 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" } + }); + } + } +} diff --git a/TechHelper.Server/Migrations/20250901083708_question_qt_update_3.Designer.cs b/TechHelper.Server/Migrations/20250901083708_question_qt_update_3.Designer.cs new file mode 100644 index 0000000..3135303 --- /dev/null +++ b/TechHelper.Server/Migrations/20250901083708_question_qt_update_3.Designer.cs @@ -0,0 +1,1299 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using TechHelper.Context; + +#nullable disable + +namespace TechHelper.Server.Migrations +{ + [DbContext(typeof(ApplicationContext))] + [Migration("20250901083708_question_qt_update_3")] + partial class question_qt_update_3 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.16") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Entities.Contracts.Assignment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnName("created_at"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("created_by"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("description"); + + b.Property("DueDate") + .HasColumnType("datetime(6)") + .HasColumnName("due_date"); + + b.Property("ExamStructId") + .HasColumnType("char(36)") + .HasColumnName("exam_struct_id"); + + b.Property("ExamType") + .HasColumnType("tinyint unsigned"); + + b.Property("IsDeleted") + .HasColumnType("tinyint(1)") + .HasColumnName("deleted"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Score") + .HasColumnType("float") + .HasColumnName("score"); + + b.Property("SubjectArea") + .HasColumnType("tinyint unsigned") + .HasColumnName("subject_area"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)") + .HasColumnName("title"); + + b.Property("TotalQuestions") + .HasColumnType("tinyint unsigned") + .HasColumnName("total_points"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + b.HasIndex("ExamStructId") + .IsUnique(); + + b.HasIndex("UserId"); + + b.ToTable("assignments", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("AssignmentId") + .HasColumnType("char(36)") + .HasColumnName("assignment_id"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)") + .HasColumnName("file_name"); + + b.Property("FilePath") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)") + .HasColumnName("file_path"); + + b.Property("IsDeleted") + .HasColumnType("tinyint(1)") + .HasColumnName("deleted"); + + b.Property("UploadedAt") + .HasColumnType("datetime(6)") + .HasColumnName("uploaded_at"); + + b.HasKey("Id"); + + b.HasIndex("AssignmentId"); + + b.ToTable("assignment_attachments"); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentClass", b => + { + b.Property("AssignmentId") + .HasColumnType("char(36)") + .HasColumnName("assignment_id") + .HasColumnOrder(0); + + b.Property("ClassId") + .HasColumnType("char(36)") + .HasColumnName("class_id") + .HasColumnOrder(1); + + b.Property("AssignedAt") + .HasColumnType("datetime(6)") + .HasColumnName("assigned_at"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.HasKey("AssignmentId", "ClassId"); + + b.HasIndex("ClassId"); + + b.ToTable("assignment_class", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("AssignmentId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnName("created_at"); + + b.Property("Index") + .HasColumnType("tinyint unsigned") + .HasColumnName("question_number"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.Property("ParentAssignmentQuestionId") + .HasColumnType("char(36)") + .HasColumnName("parent_question_group_id"); + + b.Property("QuestionContextId") + .HasColumnType("char(36)") + .HasColumnName("description"); + + b.Property("QuestionId") + .HasColumnType("char(36)") + .HasColumnName("question_id"); + + b.Property("Score") + .HasColumnType("float") + .HasColumnName("score"); + + b.Property("Sequence") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("sequence"); + + b.Property("StructType") + .HasColumnType("tinyint unsigned") + .HasColumnName("group_state"); + + b.Property("Title") + .HasMaxLength(1024) + .HasColumnType("varchar(1024)") + .HasColumnName("title"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.HasKey("Id"); + + b.HasIndex("AssignmentId"); + + b.HasIndex("ParentAssignmentQuestionId"); + + b.HasIndex("QuestionContextId"); + + b.HasIndex("QuestionId"); + + b.ToTable("assignment_questions", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.Class", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)") + .HasColumnName("created_at"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CreatedAt")); + + b.Property("Description") + .HasColumnType("longtext") + .HasColumnName("description"); + + b.Property("Grade") + .HasColumnType("tinyint unsigned") + .HasColumnName("grade"); + + b.Property("HeadTeacherId") + .HasColumnType("char(36)") + .HasColumnName("head_teacher_id"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.Property("Number") + .HasColumnType("tinyint unsigned") + .HasColumnName("class"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)") + .HasColumnName("updated_at"); + + MySqlPropertyBuilderExtensions.UseMySqlComputedColumn(b.Property("UpdatedAt")); + + b.HasKey("Id"); + + b.HasIndex("HeadTeacherId"); + + b.ToTable("classes", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.ClassStudent", b => + { + b.Property("ClassId") + .HasColumnType("char(36)") + .HasColumnName("class_id") + .HasColumnOrder(0); + + b.Property("StudentId") + .HasColumnType("char(36)") + .HasColumnName("student_id") + .HasColumnOrder(1); + + b.Property("EnrollmentDate") + .HasColumnType("datetime(6)") + .HasColumnName("enrollment_date"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.HasKey("ClassId", "StudentId"); + + b.HasIndex("StudentId"); + + b.ToTable("class_student", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.ClassTeacher", b => + { + b.Property("ClassId") + .HasColumnType("char(36)") + .HasColumnName("class_id"); + + b.Property("TeacherId") + .HasColumnType("char(36)") + .HasColumnName("teacher_id"); + + b.Property("SubjectTaught") + .HasColumnType("tinyint unsigned") + .HasColumnName("subject_taught"); + + b.HasKey("ClassId", "TeacherId"); + + b.HasIndex("TeacherId"); + + b.ToTable("class_teachers", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.Global", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("Area") + .HasColumnType("tinyint unsigned"); + + b.Property("Info") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("global"); + }); + + modelBuilder.Entity("Entities.Contracts.KeyPoint", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("LessonID") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("LessonID"); + + b.ToTable("key_point"); + }); + + modelBuilder.Entity("Entities.Contracts.Lesson", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TextbookID") + .HasColumnType("char(36)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("TextbookID"); + + b.ToTable("lesson"); + }); + + modelBuilder.Entity("Entities.Contracts.LessonQuestion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("LessonID") + .HasColumnType("char(36)"); + + b.Property("Question") + .IsRequired() + .HasMaxLength(65535) + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("LessonID"); + + b.ToTable("lesson_question"); + }); + + modelBuilder.Entity("Entities.Contracts.Question", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("Answer") + .HasMaxLength(65535) + .HasColumnType("longtext") + .HasColumnName("correct_answer"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)") + .HasColumnName("created_at"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CreatedAt")); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("created_by"); + + b.Property("DifficultyLevel") + .HasMaxLength(10) + .HasColumnType("tinyint unsigned") + .HasColumnName("difficulty_level"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.Property("KeyPointId") + .HasColumnType("char(36)") + .HasColumnName("key_point"); + + b.Property("LessonId") + .HasColumnType("char(36)") + .HasColumnName("lesson"); + + b.Property("Options") + .HasColumnType("longtext") + .HasColumnName("options"); + + b.Property("QType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SubjectArea") + .HasMaxLength(100) + .HasColumnType("tinyint unsigned") + .HasColumnName("subject_area"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(65535) + .HasColumnType("longtext") + .HasColumnName("question_text"); + + b.Property("Type") + .HasMaxLength(20) + .HasColumnType("tinyint unsigned") + .HasColumnName("question_type"); + + b.Property("UpdatedAt") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)") + .HasColumnName("updated_at"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + b.HasIndex("KeyPointId"); + + b.HasIndex("LessonId"); + + b.HasIndex("Title") + .HasAnnotation("MySql:IndexPrefixLength", new[] { 20 }); + + b.ToTable("questions", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.QuestionContext", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("QuestionContexts"); + }); + + modelBuilder.Entity("Entities.Contracts.Submission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("AssignmentId") + .HasColumnType("char(36)") + .HasColumnName("assignment_id"); + + b.Property("AttemptNumber") + .HasColumnType("tinyint unsigned") + .HasColumnName("attempt_number"); + + b.Property("ErrorQuesNum") + .HasColumnType("tinyint unsigned"); + + b.Property("GradedAt") + .HasColumnType("datetime(6)") + .HasColumnName("graded_at"); + + b.Property("GraderId") + .HasColumnType("char(36)") + .HasColumnName("graded_by"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.Property("OverallFeedback") + .HasColumnType("longtext") + .HasColumnName("overall_feedback"); + + b.Property("OverallGrade") + .HasPrecision(5, 2) + .HasColumnType("float") + .HasColumnName("overall_grade"); + + b.Property("Status") + .HasMaxLength(15) + .HasColumnType("int") + .HasColumnName("status"); + + b.Property("StudentId") + .HasColumnType("char(36)") + .HasColumnName("student_id"); + + b.Property("SubmissionTime") + .HasColumnType("datetime(6)") + .HasColumnName("submission_time"); + + b.Property("TotalQuesNum") + .HasColumnType("tinyint unsigned"); + + b.Property("TotalScore") + .HasColumnType("tinyint unsigned"); + + b.HasKey("Id"); + + b.HasIndex("AssignmentId"); + + b.HasIndex("GraderId"); + + b.HasIndex("StudentId"); + + b.ToTable("submissions", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.SubmissionDetail", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("AssignmentQuestionId") + .HasColumnType("char(36)") + .HasColumnName("assignment_question_id"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)") + .HasColumnName("created_at"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CreatedAt")); + + b.Property("IsCorrect") + .HasColumnType("tinyint(1)") + .HasColumnName("is_correct"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("deleted"); + + b.Property("PointsAwarded") + .HasPrecision(5, 2) + .HasColumnType("float") + .HasColumnName("points_awarded"); + + b.Property("Status") + .HasColumnType("int") + .HasColumnName("status"); + + b.Property("StudentAnswer") + .HasColumnType("longtext") + .HasColumnName("student_answer"); + + b.Property("StudentId") + .HasColumnType("char(36)") + .HasColumnName("student_id"); + + b.Property("SubmissionId") + .HasColumnType("char(36)") + .HasColumnName("submission_id"); + + b.Property("TeacherFeedback") + .HasColumnType("longtext") + .HasColumnName("teacher_feedback"); + + b.Property("UpdatedAt") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)") + .HasColumnName("updated_at"); + + b.HasKey("Id"); + + b.HasIndex("AssignmentQuestionId"); + + b.HasIndex("StudentId"); + + b.HasIndex("SubmissionId"); + + b.ToTable("submission_details", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.Textbook", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Grade") + .HasColumnType("tinyint unsigned"); + + b.Property("Publisher") + .HasColumnType("tinyint unsigned"); + + b.Property("SubjectArea") + .HasColumnType("tinyint unsigned"); + + b.Property("Title") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("textbook"); + }); + + modelBuilder.Entity("Entities.Contracts.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Address") + .HasColumnType("longtext"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("DisplayName") + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeleted") + .HasColumnType("tinyint(1)") + .HasColumnName("deleted"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("RefreshToken") + .HasColumnType("longtext"); + + b.Property("RefreshTokenExpiryTime") + .HasColumnType("datetime(6)"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("SubjectArea") + .HasColumnType("tinyint unsigned"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + + b.HasData( + new + { + Id = new Guid("8c6c5e8e-ef00-444c-9c7c-cba5cd6f7043"), + Name = "Student", + NormalizedName = "STUDENT" + }, + new + { + Id = new Guid("2670f35a-df0c-4071-8879-80eb99d138a1"), + Name = "Teacher", + NormalizedName = "TEACHER" + }, + new + { + Id = new Guid("9eda9d90-0cd2-4fbe-b07e-f90bd01f32db"), + Name = "Administrator", + NormalizedName = "ADMINISTRATOR" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Entities.Contracts.Assignment", b => + { + b.HasOne("Entities.Contracts.User", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.AssignmentQuestion", "ExamStruct") + .WithOne() + .HasForeignKey("Entities.Contracts.Assignment", "ExamStructId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", null) + .WithMany("CreatedAssignments") + .HasForeignKey("UserId"); + + b.Navigation("Creator"); + + b.Navigation("ExamStruct"); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentAttachment", b => + { + b.HasOne("Entities.Contracts.Assignment", "Assignment") + .WithMany("AssignmentAttachments") + .HasForeignKey("AssignmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Assignment"); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentClass", b => + { + b.HasOne("Entities.Contracts.Assignment", "Assignment") + .WithMany("AssignmentClasses") + .HasForeignKey("AssignmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.Class", "Class") + .WithMany("AssignmentClasses") + .HasForeignKey("ClassId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Assignment"); + + b.Navigation("Class"); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b => + { + b.HasOne("Entities.Contracts.Assignment", "Assignment") + .WithMany() + .HasForeignKey("AssignmentId"); + + b.HasOne("Entities.Contracts.AssignmentQuestion", "ParentAssignmentQuestion") + .WithMany("ChildrenAssignmentQuestion") + .HasForeignKey("ParentAssignmentQuestionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Entities.Contracts.QuestionContext", "QuestionContext") + .WithMany("Questions") + .HasForeignKey("QuestionContextId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Entities.Contracts.Question", "Question") + .WithMany("AssignmentQuestions") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Assignment"); + + b.Navigation("ParentAssignmentQuestion"); + + b.Navigation("Question"); + + b.Navigation("QuestionContext"); + }); + + modelBuilder.Entity("Entities.Contracts.Class", b => + { + b.HasOne("Entities.Contracts.User", "HeadTeacher") + .WithMany() + .HasForeignKey("HeadTeacherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("HeadTeacher"); + }); + + modelBuilder.Entity("Entities.Contracts.ClassStudent", b => + { + b.HasOne("Entities.Contracts.Class", "Class") + .WithMany("ClassStudents") + .HasForeignKey("ClassId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", "Student") + .WithMany("EnrolledClassesLink") + .HasForeignKey("StudentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Class"); + + b.Navigation("Student"); + }); + + modelBuilder.Entity("Entities.Contracts.ClassTeacher", b => + { + b.HasOne("Entities.Contracts.Class", "Class") + .WithMany("ClassTeachers") + .HasForeignKey("ClassId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", "Teacher") + .WithMany("TaughtClassesLink") + .HasForeignKey("TeacherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Class"); + + b.Navigation("Teacher"); + }); + + modelBuilder.Entity("Entities.Contracts.KeyPoint", b => + { + b.HasOne("Entities.Contracts.Lesson", "Lesson") + .WithMany("KeyPoints") + .HasForeignKey("LessonID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Lesson"); + }); + + modelBuilder.Entity("Entities.Contracts.Lesson", b => + { + b.HasOne("Entities.Contracts.Textbook", "Textbook") + .WithMany("Lessons") + .HasForeignKey("TextbookID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Textbook"); + }); + + modelBuilder.Entity("Entities.Contracts.LessonQuestion", b => + { + b.HasOne("Entities.Contracts.Lesson", "Lesson") + .WithMany("LessonQuestions") + .HasForeignKey("LessonID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Lesson"); + }); + + modelBuilder.Entity("Entities.Contracts.Question", b => + { + b.HasOne("Entities.Contracts.User", "Creator") + .WithMany("CreatedQuestions") + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Entities.Contracts.KeyPoint", "KeyPoint") + .WithMany("Questions") + .HasForeignKey("KeyPointId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Entities.Contracts.Lesson", "Lesson") + .WithMany("Questions") + .HasForeignKey("LessonId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Creator"); + + b.Navigation("KeyPoint"); + + b.Navigation("Lesson"); + }); + + modelBuilder.Entity("Entities.Contracts.Submission", b => + { + b.HasOne("Entities.Contracts.Assignment", "Assignment") + .WithMany("Submissions") + .HasForeignKey("AssignmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", "Grader") + .WithMany("GradedSubmissions") + .HasForeignKey("GraderId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Entities.Contracts.User", "Student") + .WithMany("SubmissionsAsStudent") + .HasForeignKey("StudentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Assignment"); + + b.Navigation("Grader"); + + b.Navigation("Student"); + }); + + modelBuilder.Entity("Entities.Contracts.SubmissionDetail", b => + { + b.HasOne("Entities.Contracts.AssignmentQuestion", "AssignmentQuestion") + .WithMany("SubmissionDetails") + .HasForeignKey("AssignmentQuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", "Student") + .WithMany("SubmissionDetails") + .HasForeignKey("StudentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.Submission", "Submission") + .WithMany("SubmissionDetails") + .HasForeignKey("SubmissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AssignmentQuestion"); + + b.Navigation("Student"); + + b.Navigation("Submission"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Entities.Contracts.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Entities.Contracts.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Entities.Contracts.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Entities.Contracts.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Entities.Contracts.Assignment", b => + { + b.Navigation("AssignmentAttachments"); + + b.Navigation("AssignmentClasses"); + + b.Navigation("Submissions"); + }); + + modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b => + { + b.Navigation("ChildrenAssignmentQuestion"); + + b.Navigation("SubmissionDetails"); + }); + + modelBuilder.Entity("Entities.Contracts.Class", b => + { + b.Navigation("AssignmentClasses"); + + b.Navigation("ClassStudents"); + + b.Navigation("ClassTeachers"); + }); + + modelBuilder.Entity("Entities.Contracts.KeyPoint", b => + { + b.Navigation("Questions"); + }); + + modelBuilder.Entity("Entities.Contracts.Lesson", b => + { + b.Navigation("KeyPoints"); + + b.Navigation("LessonQuestions"); + + b.Navigation("Questions"); + }); + + modelBuilder.Entity("Entities.Contracts.Question", b => + { + b.Navigation("AssignmentQuestions"); + }); + + modelBuilder.Entity("Entities.Contracts.QuestionContext", b => + { + b.Navigation("Questions"); + }); + + modelBuilder.Entity("Entities.Contracts.Submission", b => + { + b.Navigation("SubmissionDetails"); + }); + + modelBuilder.Entity("Entities.Contracts.Textbook", b => + { + b.Navigation("Lessons"); + }); + + modelBuilder.Entity("Entities.Contracts.User", b => + { + b.Navigation("CreatedAssignments"); + + b.Navigation("CreatedQuestions"); + + b.Navigation("EnrolledClassesLink"); + + b.Navigation("GradedSubmissions"); + + b.Navigation("SubmissionDetails"); + + b.Navigation("SubmissionsAsStudent"); + + b.Navigation("TaughtClassesLink"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/TechHelper.Server/Migrations/20250901083708_question_qt_update_3.cs b/TechHelper.Server/Migrations/20250901083708_question_qt_update_3.cs new file mode 100644 index 0000000..cb7e822 --- /dev/null +++ b/TechHelper.Server/Migrations/20250901083708_question_qt_update_3.cs @@ -0,0 +1,82 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace TechHelper.Server.Migrations +{ + /// + public partial class question_qt_update_3 : Migration + { + /// + 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( + 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" } + }); + } + + /// + 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" } + }); + } + } +} diff --git a/TechHelper.Server/Migrations/ApplicationContextModelSnapshot.cs b/TechHelper.Server/Migrations/ApplicationContextModelSnapshot.cs index d50daf4..4c2f81e 100644 --- a/TechHelper.Server/Migrations/ApplicationContextModelSnapshot.cs +++ b/TechHelper.Server/Migrations/ApplicationContextModelSnapshot.cs @@ -219,6 +219,9 @@ namespace TechHelper.Server.Migrations .HasColumnType("varchar(1024)") .HasColumnName("title"); + b.Property("Type") + .HasColumnType("tinyint unsigned"); + b.HasKey("Id"); b.HasIndex("AssignmentId"); @@ -332,6 +335,25 @@ namespace TechHelper.Server.Migrations b.ToTable("class_teachers", (string)null); }); + modelBuilder.Entity("Entities.Contracts.Global", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnName("id"); + + b.Property("Area") + .HasColumnType("tinyint unsigned"); + + b.Property("Info") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("global"); + }); + modelBuilder.Entity("Entities.Contracts.KeyPoint", b => { b.Property("Id") @@ -445,6 +467,10 @@ namespace TechHelper.Server.Migrations .HasColumnType("longtext") .HasColumnName("options"); + b.Property("QType") + .IsRequired() + .HasColumnType("longtext"); + b.Property("SubjectArea") .HasMaxLength(100) .HasColumnType("tinyint unsigned") @@ -723,6 +749,9 @@ namespace TechHelper.Server.Migrations b.Property("SecurityStamp") .HasColumnType("longtext"); + b.Property("SubjectArea") + .HasColumnType("tinyint unsigned"); + b.Property("TwoFactorEnabled") .HasColumnType("tinyint(1)"); @@ -771,19 +800,19 @@ namespace TechHelper.Server.Migrations b.HasData( new { - Id = new Guid("df89b9a0-65ef-42dd-b2cb-e59997a72e70"), + Id = new Guid("8c6c5e8e-ef00-444c-9c7c-cba5cd6f7043"), Name = "Student", NormalizedName = "STUDENT" }, new { - Id = new Guid("0775702a-5db7-4747-94d0-4376fad2b58b"), + Id = new Guid("2670f35a-df0c-4071-8879-80eb99d138a1"), Name = "Teacher", NormalizedName = "TEACHER" }, new { - Id = new Guid("37f41430-0cb7-44e5-988b-976200bd602d"), + Id = new Guid("9eda9d90-0cd2-4fbe-b07e-f90bd01f32db"), Name = "Administrator", NormalizedName = "ADMINISTRATOR" }); diff --git a/TechHelper.Server/Program.cs b/TechHelper.Server/Program.cs index 717c971..a489afd 100644 --- a/TechHelper.Server/Program.cs +++ b/TechHelper.Server/Program.cs @@ -17,9 +17,9 @@ using Microsoft.OpenApi.Models; var builder = WebApplication.CreateBuilder(args); -builder.Services.AddControllers(); // MVC ( API) +builder.Services.AddControllers(); // 添加 MVC 控制器服务 (用于 API) -// 2. ݿ (DbContext) +// 2. 数据库服务 (DbContext) builder.Services.AddDbContext(options => options.UseMySql( builder.Configuration.GetConnectionString("XSDB"), @@ -34,17 +34,18 @@ builder.Services.AddDbContext(options => .AddCustomRepository() .AddCustomRepository() .AddCustomRepository() -.AddCustomRepository(); +.AddCustomRepository() +.AddCustomRepository(); builder.Services.AddAutoMapper(typeof(AutoMapperProFile).Assembly); -// 3. ÷ (IOptions) +// 3. 配置服务 (IOptions) builder.Services.Configure(builder.Configuration.GetSection("ApiConfiguration")); builder.Services.Configure(builder.Configuration.GetSection("JWTSettings")); -// 4. ֤Ȩ (Identity, JWT, Զ Auth) -// ASP.NET Core Identity (Ĭϵ Cookie ֤Ȩ) +// 4. 认证和授权服务 (Identity, JWT, 自定义 Auth) +// 添加 ASP.NET Core Identity (包含默认的 Cookie 认证和授权服务) builder.Services.AddIdentity>(opt => { opt.User.AllowedUserNameCharacters = ""; @@ -60,25 +61,25 @@ builder.Services.Configure(Options => }); -// JWT Bearer ֤ +// 添加 JWT Bearer 认证方案 var jwtSettings = builder.Configuration.GetSection("JWTSettings"); builder.Services.AddAuthentication(options => { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; // Ĭ֤Ϊ JWT Bearer - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; // ĬսΪ JWT Bearer + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; // 设置默认认证方案为 JWT Bearer + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; // 设置默认挑战方案为 JWT Bearer }) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { - ValidateIssuer = true, // ֤ǩ - ValidateAudience = true, // ֤ - ValidateLifetime = true, // ֤Ч - ValidateIssuerSigningKey = true, // ֤ǩԿ + ValidateIssuer = true, // 验证签发人 + ValidateAudience = true, // 验证受众 + ValidateLifetime = true, // 验证令牌有效期 + ValidateIssuerSigningKey = true, // 验证签名密钥 - ValidIssuer = jwtSettings["validIssuer"], // Ϸǩ - ValidAudience = jwtSettings["validAudience"], // Ϸ - IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["securityKey"])) // ǩԿ + ValidIssuer = jwtSettings["validIssuer"], // 合法的签发人 + ValidAudience = jwtSettings["validAudience"], // 合法的受众 + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["securityKey"])) // 签名密钥 }; }); @@ -90,6 +91,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddEndpointsApiExplorer(); @@ -128,7 +130,7 @@ builder.Services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", builder => builder - .WithOrigins("https://localhost:7047", "http://localhost:7047") + .WithOrigins("https://localhost:7047", "http://localhost:7047", "https://localhost:5001", "http://localhost:5001") .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials()); diff --git a/TechHelper.Server/Repository/GlobalRepository.cs b/TechHelper.Server/Repository/GlobalRepository.cs new file mode 100644 index 0000000..bd6d17a --- /dev/null +++ b/TechHelper.Server/Repository/GlobalRepository.cs @@ -0,0 +1,17 @@ +using Entities.Contracts; +using Microsoft.EntityFrameworkCore; +using SharedDATA.Api; +using TechHelper.Context; + +namespace TechHelper.Repository +{ + public class GlobalRepository : Repository, IRepository + { + public GlobalRepository(ApplicationContext dbContext) : base(dbContext) + { + + } + + + } +} diff --git a/TechHelper.Server/Services/INoteService.cs b/TechHelper.Server/Services/INoteService.cs new file mode 100644 index 0000000..9a4ef54 --- /dev/null +++ b/TechHelper.Server/Services/INoteService.cs @@ -0,0 +1,13 @@ +using Entities.Contracts; +using Entities.DTO; +using System.Net; + +namespace TechHelper.Services +{ + + + public interface INoteService : IBaseService + { + + } +} diff --git a/TechHelper.Server/Services/NoteService.cs b/TechHelper.Server/Services/NoteService.cs new file mode 100644 index 0000000..814a3a2 --- /dev/null +++ b/TechHelper.Server/Services/NoteService.cs @@ -0,0 +1,107 @@ +using AutoMapper; +using Entities.Contracts; +using Entities.DTO; +using Microsoft.AspNetCore.Identity; +using SharedDATA.Api; +using System.Net; + +namespace TechHelper.Services +{ + public class NoteService : INoteService + { + private readonly IUnitOfWork _work; + private readonly IMapper _mapper; + + public NoteService(IUnitOfWork work) + { + _work = work; + } + + public async Task AddAsync(GlobalDto model) + { + try + { + var globalEntity = new Global + { + Area = model.SubjectArea, + Info = model.Data + }; + + await _work.GetRepository().InsertAsync(globalEntity); + await _work.SaveChangesAsync(); + + return ApiResponse.Success("数据已成功添加。"); + } + catch (Exception ex) + { + return ApiResponse.Error($"添加数据时发生错误: {ex.Message}"); + } + } + + public async Task DeleteAsync(byte id) + { + var globalRepo = _work.GetRepository(); + var globalEntity = await globalRepo.GetFirstOrDefaultAsync(predicate: x => x.Area == (SubjectAreaEnum)id); + + if (globalEntity == null) + { + return ApiResponse.Error("未找到要删除的数据。"); + } + + globalRepo.Delete(globalEntity); + await _work.SaveChangesAsync(); + + return ApiResponse.Success("数据已成功删除。"); + } + + public async Task GetAllAsync(QueryParameter query) + { + var repository = _work.GetRepository(); + // 获取所有实体,并将其 Info 属性作为结果返回 + var entities = await repository.GetAllAsync(); + + // 直接返回字符串列表 + var resultData = entities.Select(e => e.Info).ToList(); + + return ApiResponse.Success("数据已成功检索。", resultData); + } + + public async Task GetAsync(byte id) + { + var globalEntity = await _work.GetRepository().GetFirstOrDefaultAsync(predicate: x => x.Area == (SubjectAreaEnum)id); + + if (globalEntity == null) + { + return ApiResponse.Error("未找到数据。"); + } + + // 直接返回 Info 字符串 + return ApiResponse.Success("数据已成功检索。", globalEntity.Info); + } + + public async Task UpdateAsync(GlobalDto model) + { + try + { + var repository = _work.GetRepository(); + var existingEntity = await repository.GetFirstOrDefaultAsync(predicate: x => x.Area == (SubjectAreaEnum)model.SubjectArea); + + if (existingEntity == null) + { + return ApiResponse.Error("未找到要更新的数据。"); + } + + // 直接将传入的字符串赋值给 Info 属性 + existingEntity.Info = model.Data; + repository.Update(existingEntity); + await _work.SaveChangesAsync(); + + return ApiResponse.Success("数据已成功更新。"); + } + catch (Exception ex) + { + return ApiResponse.Error($"更新数据时发生错误: {ex.Message}"); + } + } + } +} diff --git a/TechHelper.Server/TechHelper.Server.csproj b/TechHelper.Server/TechHelper.Server.csproj index 407c0f9..5c00dd7 100644 --- a/TechHelper.Server/TechHelper.Server.csproj +++ b/TechHelper.Server/TechHelper.Server.csproj @@ -23,6 +23,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive +