AsiignmentStruct

This commit is contained in:
SpecialX
2025-06-20 18:58:11 +08:00
parent d20c051c51
commit 681c0862b6
32 changed files with 414 additions and 752 deletions

View File

@@ -26,12 +26,12 @@ namespace TechHelper.Client.Exam
Enum.TryParse<SubjectAreaEnum>(examPaper.SubjectArea, out SubjectArea);
dto.SubjectArea = SubjectArea;
AssignmentStructDto examStruct = new AssignmentStructDto();
AssignmentQuestionDto examStruct = new AssignmentQuestionDto();
foreach (var qg in examPaper.QuestionGroups)
{
examStruct.ChildrenGroups.Add(ParseMajorQuestionGroup(qg));
examStruct.ChildrenGroups.Last().Index = (byte)(examStruct.ChildrenGroups.Count());
examStruct.ChildrenAssignmentQuestion.Add(ParseMajorQuestionGroup(qg));
examStruct.ChildrenAssignmentQuestion.Last().Index = (byte)(examStruct.ChildrenAssignmentQuestion.Count());
}
dto.ExamStruct = examStruct;
@@ -39,28 +39,20 @@ namespace TechHelper.Client.Exam
return dto;
}
private static AssignmentStructDto ParseMajorQuestionGroup(MajorQuestionGroup sqg)
private static AssignmentQuestionDto ParseMajorQuestionGroup(MajorQuestionGroup sqg)
{
var examStruct = new AssignmentStructDto();
var examStruct = new AssignmentQuestionDto();
examStruct.Title = sqg.Title;
examStruct.Score = sqg.Score;
if (sqg.SubQuestionGroups != null)
{
examStruct.Title = sqg.Title;
examStruct.Score = sqg.Score;
examStruct.ChildrenGroups = new List<AssignmentStructDto>();
examStruct.ChildrenAssignmentQuestion = new List<AssignmentQuestionDto>();
sqg.SubQuestionGroups?.ForEach(ssqg =>
{
if (string.IsNullOrEmpty(ssqg.Descript))
{
examStruct.ChildrenGroups.Add(ParseMajorQuestionGroup(ssqg));
examStruct.ChildrenGroups.Last().Index = (byte)(examStruct.ChildrenGroups.Count());
}
else
{
examStruct.AssignmentQuestions.Add(ParseGroupToAssignmentQuestion(ssqg, false));
examStruct.AssignmentQuestions.Last().Index = (byte)(examStruct.AssignmentQuestions.Count());
}
examStruct.ChildrenAssignmentQuestion.Add(ParseMajorQuestionGroup(ssqg));
examStruct.ChildrenAssignmentQuestion.Last().Index = (byte)(examStruct.ChildrenAssignmentQuestion.Count());
});
@@ -72,12 +64,8 @@ namespace TechHelper.Client.Exam
sqg.SubQuestions?.ForEach(sq =>
{
if(sq.SubQuestions.Any())
{
}
examStruct.AssignmentQuestions.Add(ParseAssignmentQuestion(sq));
examStruct.AssignmentQuestions.Last().Index = (byte)(examStruct.AssignmentQuestions.Count());
examStruct.ChildrenAssignmentQuestion.Add(ParseAssignmentQuestion(sq));
examStruct.ChildrenAssignmentQuestion.Last().Index = (byte)(examStruct.ChildrenAssignmentQuestion.Count());
});
}
@@ -91,47 +79,6 @@ namespace TechHelper.Client.Exam
.Where(line => !string.IsNullOrWhiteSpace(line)).ToList();
}
private static QuestionDto ParseGroupToQuestion(MajorQuestionGroup qg, bool subQ = true)
{
var dq = new QuestionDto();
dq.Title = qg.Title + Environment.NewLine + qg.Descript;
if (subQ) dq.GroupState = QuestionGroupState.Subquestion;
else dq.GroupState = QuestionGroupState.Group;
qg.SubQuestions?.ForEach(ssq =>
{
dq.ChildrenQuestion.Add(ParseQuestion(ssq));
});
qg.SubQuestionGroups?.ForEach(sqg =>
{
dq.ChildrenQuestion.Add(ParseGroupToQuestion(sqg));
});
return dq;
}
private static AssignmentQuestionDto ParseGroupToAssignmentQuestion(MajorQuestionGroup qg, bool subQ = true)
{
var aq = new AssignmentQuestionDto();
aq.Score = qg.Score;
qg.SubQuestions?.ForEach(ssq =>
{
aq.Question.ChildrenQuestion.Add(ParseQuestion(ssq));
aq.Question.ChildrenQuestion.Last().Index = (byte)aq.Question.ChildrenQuestion.Count;
});
qg.SubQuestionGroups?.ForEach(sqg =>
{
aq.Question.ChildrenQuestion.Add(ParseGroupToQuestion(sqg));
aq.Question.ChildrenQuestion.Last().Index = (byte)aq.Question.ChildrenQuestion.Count;
});
return aq;
}
private static AssignmentQuestionDto ParseAssignmentQuestion(PaperQuestion sq)
{
@@ -143,8 +90,8 @@ namespace TechHelper.Client.Exam
sq.SubQuestions?.ForEach(ssq =>
{
aq.Question.ChildrenQuestion.Add(ParseQuestion(ssq));
aq.Question.ChildrenQuestion.Last().Index = (byte)aq.Question.ChildrenQuestion.Count;
aq.ChildrenAssignmentQuestion.Add(ParseAssignmentQuestion(ssq));
aq.ChildrenAssignmentQuestion.Last().Index = (byte)aq.ChildrenAssignmentQuestion.Count;
});
@@ -156,14 +103,6 @@ namespace TechHelper.Client.Exam
var dq = new QuestionDto();
dq.Title = sq.Stem;
dq.Options = string.Join(Environment.NewLine, sq.Options.Select(opt => $"{opt.Label} {opt.Text}"));
dq.Score = sq.Score;
sq.SubQuestions?.ForEach(ssq =>
{
dq.ChildrenQuestion.Add(ParseQuestion(ssq));
dq.ChildrenQuestion.Last().Index = (byte)dq.ChildrenQuestion.Count;
});
return dq;
}

View File

@@ -6,14 +6,14 @@ using System.Text.RegularExpressions;
namespace TechHelper.Client.Exam
{
// --- 新增错误处理相关类 ---
public class ParseError
{
public ParseErrorType Type { get; }
public string Message { get; }
public int? Index { get; } // 错误发生的文本索引或匹配项索引
public string MatchedText { get; } // 如果与某个匹配项相关,记录其文本
public Exception InnerException { get; } // 捕获到的原始异常
public int? Index { get; }
public string MatchedText { get; }
public Exception InnerException { get; }
public ParseError(ParseErrorType type, string message, int? index = null, string matchedText = null, Exception innerException = null)
{

View File

@@ -0,0 +1,17 @@
@using Entities.DTO
@using TechHelper.Client.Exam
<MudPaper>
<MudText>@AssignmentQuestion.Id</MudText>
<MudTextField @bind-Value="AssignmentQuestion.Title" Label="Title" Variant="Variant.Outlined" Margin="Margin.Dense" AutoFocus="true" />
<MudTextField @bind-Value="AssignmentQuestion.Index" Label="Index" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="." Margin="Margin.Dense" AutoFocus="true" />
<MudTextField @bind-Value="AssignmentQuestion.Score" Label="Score" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="." Margin="Margin.Dense" AutoFocus="true" />
<QuestionEdit Question="AssignmentQuestion.Question"/>
</MudPaper>
@code {
[Parameter]
public AssignmentQuestionDto AssignmentQuestion { get; set; } = new AssignmentQuestionDto();
}

View File

@@ -9,20 +9,32 @@
@using System.Globalization;
@using TechHelper.Client.Pages.Editor
<MudPaper Elevation="5" Class="d-flex overflow-hidden flex-grow-1" Style="overflow:hidden; position:relative;height:100%">
<MudDrawerContainer Class="mud-height-full flex-grow-1" Style="height:100%">
<MudDrawer @bind-Open="@_open" Elevation="0" Variant="@DrawerVariant.Persistent" Color="Color.Primary" Anchor="Anchor.End" OverlayAutoClose="true">
<MudDrawerHeader>
<MudText Typo="Typo.h6"> 配置 </MudText>
</MudDrawerHeader>
<MudStack Class="overflow-auto">
<ParseRoleConfig />
<MudButton Color="Color.Success"> ParseExam </MudButton>
</MudStack>
@if (_edit)
{
<AssignmentQuestionEdit AssignmentQuestion="selectedAssignmentQuestion" />
}
else
{
<MudDrawerHeader>
<MudText Typo="Typo.h6"> 配置 </MudText>
</MudDrawerHeader>
<MudStack Class="overflow-auto">
<ParseRoleConfig />
<MudButton Color="Color.Success"> ParseExam </MudButton>
</MudStack>
}
</MudDrawer>
<MudStack Row="true" Class="flex-grow-1" Style="height:100%">
<ExamView Class="overflow-auto" ParsedExam="ExamContent"></ExamView>
<ExamView Class="overflow-auto" ClickedStruct="HandleClickedStruct" ParsedExam="ExamContent"></ExamView>
<MudPaper Class="ma-2">
<MudPaper Elevation="0" Style="height:calc(100% - 80px)">
@@ -75,11 +87,15 @@
[CascadingParameter]
private Task<AuthenticationState> authenticationStateTask { get; set; }
private AssignmentQuestionDto selectedAssignmentQuestion = new AssignmentQuestionDto();
private bool _open = false;
private bool _edit = false;
private void ToggleDrawer()
{
_open = !_open;
_edit = false;
}
private BlazoredTextEditor _textEditor = new BlazoredTextEditor();
private ExamPaper _parsedExam = new ExamPaper();
@@ -87,6 +103,14 @@
private ExamParserConfig _examParserConfig { get; set; } = new ExamParserConfig();
private void HandleClickedStruct(AssignmentQuestionDto dto)
{
_open = true;
_edit = true;
selectedAssignmentQuestion = dto;
StateHasChanged();
}
private async Task ParseExam()
{

View File

@@ -1,36 +0,0 @@
@using Entities.DTO
@using TechHelper.Client.Exam
<MudPaper Elevation=@Elevation Class=@Class>
<MudStack Row="true">
<MudText Typo="Typo.h6">@ExamStruct.Title</MudText>
@if (ExamStruct.Score > 0)
{
<MudText Typo="Typo.body2"><b>总分:</b> @ExamStruct.Score 分</MudText>
}
</MudStack>
@foreach (var childStruct in ExamStruct.ChildrenGroups)
{
<ExamGroupView ExamStruct="childStruct"/>
}
@foreach (var question in ExamStruct.AssignmentQuestions)
{
<QuestionCard Question="question.Question" Elevation=@Elevation Class="my-2 pa-1" />
}
</MudPaper>
@code {
[Parameter]
public AssignmentStructDto ExamStruct { get; set; } = new AssignmentStructDto();
[Parameter]
public string Class { get; set; } = "my-2 pa-1";
[Parameter]
public int Elevation { get; set; } = 0;
}

View File

@@ -0,0 +1,51 @@
@using Entities.DTO
@using TechHelper.Client.Exam
<MudPaper @onclick:stopPropagation>
<MudPaper Elevation=@Elevation Class=@Class @onclick="HandleClick">
<MudStack Row="true">
<MudText Typo="Typo.h6">@ExamStruct.Title</MudText>
@if (ExamStruct.Score > 0)
{
<MudText Typo="Typo.body2"><b>总分:</b> @ExamStruct.Score 分</MudText>
}
</MudStack>
@if (ExamStruct.Question != null)
{
<QuestionCard Question="ExamStruct.Question" Index="ExamStruct.Index" Elevation=@Elevation Class="my-2 pa-1" />
}
@foreach (var examStruct in ExamStruct.ChildrenAssignmentQuestion)
{
<ExamStructView ExamStruct="examStruct" ClickedStruct="HandleChildStructClick" Elevation=@Elevation Class="my-2 pa-1" />
}
</MudPaper>
</MudPaper>
@code {
[Parameter]
public AssignmentQuestionDto ExamStruct { get; set; } = new AssignmentQuestionDto();
[Parameter]
public EventCallback<AssignmentQuestionDto> ClickedStruct { get; set; }
[Parameter]
public string Class { get; set; } = "my-2 pa-1";
[Parameter]
public int Elevation { get; set; } = 0;
private async void HandleClick()
{
await ClickedStruct.InvokeAsync(ExamStruct);
}
private async void HandleChildStructClick(AssignmentQuestionDto clickedChildExamStruct)
{
await ClickedStruct.InvokeAsync(clickedChildExamStruct);
}
}

View File

@@ -8,7 +8,7 @@
<MudText Class="d-flex justify-content-center" Typo="Typo.h6"> @ParsedExam.Title </MudText>
<MudText Typo="Typo.body1"> @ParsedExam.Description </MudText>
<ExamGroupView ExamStruct="@ParsedExam.ExamStruct" Elevation="1" Class="ma-0 pa-2" />
<ExamStructView ExamStruct="@ParsedExam.ExamStruct" Elevation="1" ClickedStruct="HandleClickedStruct" Class="ma-0 pa-2" />
</MudPaper>
}
@@ -25,6 +25,10 @@ else
[Parameter]
public AssignmentDto ParsedExam { get; set; } = new AssignmentDto();
[Parameter]
public EventCallback<AssignmentQuestionDto> ClickedStruct { get; set; }
[Parameter]
public string Height { get; set; } = "100%";
[Parameter]
@@ -33,4 +37,10 @@ else
public string Class { get; set; } = "";
[Parameter]
public string Style { get; set; } = "";
private void HandleClickedStruct(AssignmentQuestionDto dto)
{
ClickedStruct.InvokeAsync(dto);
}
}

View File

@@ -4,14 +4,14 @@
<MudPaper Class=@Class Elevation=@Elevation Outlined="false">
<MudText Typo="Typo.subtitle1">
<b>@Question.Index</b> @((MarkupString)Question.Title.Replace("\n", "<br />"))
@if (Question.Score > 0)
<b>@Index</b> @((MarkupString)Question.Title.Replace("\n", "<br />"))
@if (Score > 0)
{
<MudText Typo="Typo.body2" Class="d-inline ml-2">(@Question.Score 分)</MudText>
<MudText Typo="Typo.body2" Class="d-inline ml-2">(@Score 分)</MudText>
}
</MudText>
@if (Question.Options != null)
@if (!string.IsNullOrEmpty(Question.Options))
{
<div class="mt-2">
@foreach (var option in Question.Options.ParseOptionsFromText())
@@ -22,12 +22,6 @@
</div>
}
@foreach(var item in Question.ChildrenQuestion)
{
<QuestionCard Question="item"/>
}
</MudPaper>
@code {
@@ -35,7 +29,13 @@
public QuestionDto Question { get; set; } = new QuestionDto();
[Parameter]
public string Class { get; set; }
public byte Index { get; set; } = 0;
[Parameter]
public byte Score { get; set; } = 0;
[Parameter]
public string Class { get; set; } = string.Empty;
[Parameter]
public int Elevation { get; set; }

View File

@@ -0,0 +1,17 @@
@using Entities.DTO
@using TechHelper.Client.Exam
<MudPaper>
<MudText>@Question.Id</MudText>
<MudTextField @bind-Value="Question.Title" Label="Title" Variant="Variant.Outlined" Margin="Margin.Dense" AutoGrow="true" />
<MudTextField @bind-Value="Question.Answer" Label="Answer" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="." Margin="Margin.Dense" AutoGrow="true" />
<MudTextField @bind-Value="Question.Options" Label="Options" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentText="." Margin="Margin.Dense" AutoGrow="true" />
</MudPaper>
@code {
[Parameter]
public QuestionDto Question { get; set; } = new QuestionDto();
}