struct&&assiQues
This commit is contained in:
@@ -1,67 +1,173 @@
|
||||
using Entities.DTO;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json;
|
||||
using Entities.Contracts;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace TechHelper.Client.Exam
|
||||
{
|
||||
public class ParentStructInfo
|
||||
{
|
||||
public string Number { get; set; }
|
||||
public SubjectAreaEnum SubjectArea { get; set; }
|
||||
public byte Index { get; set; }
|
||||
}
|
||||
|
||||
public static class ExamPaperExtensions
|
||||
{
|
||||
public static ExamDto ConvertToExamDTO(this ExamPaper examPaper)
|
||||
public static AssignmentDto ConvertToExamDTO(this ExamPaper examPaper)
|
||||
{
|
||||
ExamDto dto = new ExamDto();
|
||||
AssignmentDto dto = new AssignmentDto();
|
||||
|
||||
dto.AssignmentTitle = examPaper.AssignmentTitle;
|
||||
dto.Title = examPaper.AssignmentTitle;
|
||||
dto.Description = examPaper.Description;
|
||||
dto.SubjectArea = examPaper.SubjectArea;
|
||||
dto.QuestionGroups.Title = examPaper.AssignmentTitle;
|
||||
dto.QuestionGroups.Descript = examPaper.Description;
|
||||
|
||||
var SubjectArea = SubjectAreaEnum.Literature;
|
||||
Enum.TryParse<SubjectAreaEnum>(examPaper.SubjectArea, out SubjectArea);
|
||||
dto.SubjectArea = SubjectArea;
|
||||
|
||||
AssignmentStructDto examStruct = new AssignmentStructDto();
|
||||
|
||||
foreach (var qg in examPaper.QuestionGroups)
|
||||
{
|
||||
var qgd = new QuestionGroupDto();
|
||||
ParseMajorQuestionGroup(qg, qgd, false);
|
||||
dto.QuestionGroups.SubQuestionGroups.Add(qgd);
|
||||
examStruct.ChildrenGroups.Add(ParseMajorQuestionGroup(qg));
|
||||
examStruct.ChildrenGroups.Last().Index = (byte)(examStruct.ChildrenGroups.Count());
|
||||
}
|
||||
|
||||
|
||||
foreach (var question in examPaper.TopLevelQuestions)
|
||||
{
|
||||
if (question.SubQuestions != null && question.SubQuestions.Any())
|
||||
{
|
||||
var qgDto = new QuestionGroupDto
|
||||
{
|
||||
Title = question.Stem,
|
||||
Score = (int)question.Score,
|
||||
Descript = "",
|
||||
};
|
||||
|
||||
qgDto.ValidQuestionGroup = !string.IsNullOrEmpty(qgDto.Descript);
|
||||
|
||||
|
||||
ParseQuestionWithSubQuestions(question, qgDto, qgDto.ValidQuestionGroup);
|
||||
dto.QuestionGroups.SubQuestionGroups.Add(qgDto);
|
||||
}
|
||||
else
|
||||
{
|
||||
var qgDto = new QuestionGroupDto
|
||||
{
|
||||
Title = question.Stem,
|
||||
Score = (int)question.Score,
|
||||
Descript = "",
|
||||
};
|
||||
|
||||
qgDto.ValidQuestionGroup = !string.IsNullOrEmpty(qgDto.Descript);
|
||||
|
||||
var subQuestionDto = new SubQuestionDto();
|
||||
ParseSingleQuestion(question, subQuestionDto, !qgDto.ValidQuestionGroup);
|
||||
qgDto.SubQuestions.Add(subQuestionDto);
|
||||
dto.QuestionGroups.SubQuestionGroups.Add(qgDto);
|
||||
}
|
||||
}
|
||||
dto.ExamStruct = examStruct;
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
private static AssignmentStructDto ParseMajorQuestionGroup(MajorQuestionGroup sqg)
|
||||
{
|
||||
var examStruct = new AssignmentStructDto();
|
||||
|
||||
if (sqg.SubQuestionGroups != null)
|
||||
{
|
||||
|
||||
examStruct.Title = sqg.Title;
|
||||
examStruct.Score = sqg.Score;
|
||||
examStruct.ChildrenGroups = new List<AssignmentStructDto>();
|
||||
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());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (sqg.SubQuestions != null)
|
||||
{
|
||||
|
||||
sqg.SubQuestions?.ForEach(sq =>
|
||||
{
|
||||
if(sq.SubQuestions.Any())
|
||||
{
|
||||
|
||||
}
|
||||
examStruct.AssignmentQuestions.Add(ParseAssignmentQuestion(sq));
|
||||
examStruct.AssignmentQuestions.Last().Index = (byte)(examStruct.AssignmentQuestions.Count());
|
||||
});
|
||||
}
|
||||
|
||||
return examStruct;
|
||||
}
|
||||
|
||||
|
||||
public static List<string> ParseOptionsFromText(this string optionsText)
|
||||
{
|
||||
return optionsText.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None)
|
||||
.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)
|
||||
{
|
||||
var aq = new AssignmentQuestionDto();
|
||||
aq.Score = sq.Score;
|
||||
|
||||
aq.Question = ParseQuestion(sq);
|
||||
|
||||
sq.SubQuestions?.ForEach(ssq =>
|
||||
{
|
||||
|
||||
aq.Question.ChildrenQuestion.Add(ParseQuestion(ssq));
|
||||
aq.Question.ChildrenQuestion.Last().Index = (byte)aq.Question.ChildrenQuestion.Count;
|
||||
|
||||
});
|
||||
|
||||
return aq;
|
||||
}
|
||||
|
||||
private static QuestionDto ParseQuestion(PaperQuestion sq)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
private static void ParseMajorQuestionGroup(MajorQuestionGroup qg, QuestionGroupDto qgd, bool isParentGroupValidChain)
|
||||
{
|
||||
qgd.Title = qg.Title;
|
||||
@@ -86,12 +192,10 @@ namespace TechHelper.Client.Exam
|
||||
});
|
||||
}
|
||||
|
||||
// 处理 MajorQuestionGroup 下的 SubQuestions
|
||||
if (qg.SubQuestions != null)
|
||||
{
|
||||
qg.SubQuestions.ForEach(sq =>
|
||||
{
|
||||
// 如果 MajorQuestionGroup 下的 Question 包含子问题,则转为 QuestionGroupDto
|
||||
if (sq.SubQuestions != null && sq.SubQuestions.Any())
|
||||
{
|
||||
var subQgd = new QuestionGroupDto
|
||||
@@ -101,7 +205,6 @@ namespace TechHelper.Client.Exam
|
||||
Score = (int)sq.Score,
|
||||
Descript = "" // 默认为空
|
||||
};
|
||||
// 判断当前组是否有效:如果有描述,并且其父级链中没有任何一个组是有效组,则当前组有效
|
||||
subQgd.ValidQuestionGroup = !string.IsNullOrEmpty(subQgd.Descript) && !nextIsParentGroupValidChain;
|
||||
|
||||
ParseQuestionWithSubQuestions(sq, subQgd, subQgd.ValidQuestionGroup || nextIsParentGroupValidChain);
|
||||
@@ -121,7 +224,7 @@ namespace TechHelper.Client.Exam
|
||||
|
||||
// 解析包含子问题的 Question,将其转换为 QuestionGroupDto
|
||||
// isParentGroupValidChain 参数表示从顶层到当前组的任一父组是否已经是“有效组”
|
||||
private static void ParseQuestionWithSubQuestions(Question question, QuestionGroupDto qgd, bool isParentGroupValidChain)
|
||||
private static void ParseQuestionWithSubQuestions(PaperQuestion question, QuestionGroupDto qgd, bool isParentGroupValidChain)
|
||||
{
|
||||
qgd.Title = question.Stem;
|
||||
qgd.Score = (int)question.Score;
|
||||
@@ -165,7 +268,7 @@ namespace TechHelper.Client.Exam
|
||||
}
|
||||
|
||||
// 解析单个 Question (没有子问题) 为 SubQuestionDto
|
||||
private static void ParseSingleQuestion(Question question, SubQuestionDto subQd, bool validQ)
|
||||
private static void ParseSingleQuestion(PaperQuestion question, SubQuestionDto subQd, bool validQ)
|
||||
{
|
||||
subQd.Stem = question.Stem;
|
||||
subQd.Score = (int)question.Score;
|
||||
@@ -187,7 +290,7 @@ namespace TechHelper.Client.Exam
|
||||
|
||||
public static void SeqIndex(this ExamDto dto)
|
||||
{
|
||||
dto.QuestionGroups.SeqQGroupIndex();
|
||||
dto.ExamStruct.SeqQGroupIndex();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -51,7 +51,7 @@ namespace TechHelper.Client.Exam
|
||||
public string Description { get; set; } = "未识别试卷描述";
|
||||
public string SubjectArea { get; set; } = "试卷类别";
|
||||
public List<MajorQuestionGroup> QuestionGroups { get; set; } = new List<MajorQuestionGroup>();
|
||||
public List<Question> TopLevelQuestions { get; set; } = new List<Question>();
|
||||
public List<PaperQuestion> TopLevelQuestions { get; set; } = new List<PaperQuestion>();
|
||||
public List<ParseError> Errors { get; set; } = new List<ParseError>();
|
||||
}
|
||||
|
||||
@@ -61,17 +61,18 @@ namespace TechHelper.Client.Exam
|
||||
public string Descript { get; set; } = string.Empty;
|
||||
public float Score { get; set; }
|
||||
public List<MajorQuestionGroup> SubQuestionGroups { get; set; } = new List<MajorQuestionGroup>();
|
||||
public List<Question> SubQuestions { get; set; } = new List<Question>();
|
||||
public List<PaperQuestion> SubQuestions { get; set; } = new List<PaperQuestion>();
|
||||
public int Priority { get; set; }
|
||||
public bool bGroup { get; set; } = true;
|
||||
}
|
||||
|
||||
public class Question
|
||||
public class PaperQuestion
|
||||
{
|
||||
public string Number { get; set; } = string.Empty;
|
||||
public string Stem { get; set; } = string.Empty;
|
||||
public float Score { get; set; }
|
||||
public List<Option> Options { get; set; } = new List<Option>();
|
||||
public List<Question> SubQuestions { get; set; } = new List<Question>();
|
||||
public List<PaperQuestion> SubQuestions { get; set; } = new List<PaperQuestion>();
|
||||
public string SampleAnswer { get; set; } = string.Empty;
|
||||
public string QuestionType { get; set; } = string.Empty;
|
||||
public int Priority { get; set; }
|
||||
@@ -120,17 +121,17 @@ namespace TechHelper.Client.Exam
|
||||
public ExamParserConfig()
|
||||
{
|
||||
MajorQuestionGroupPatterns.Add(new RegexPatternConfig(@"^([一二三四五六七八九十]+)[、\.]\s*(.+?)(?:\s*\(((\d+(?:\.\d+)?))\s*分\))?\s*$", 1));
|
||||
MajorQuestionGroupPatterns.Add(new RegexPatternConfig(@"^\(([一二三四五六七八九十]{1,2}|十[一二三四五六七八九])\)\s*(.+?)(?:\s*\(((\d+(?:\.\d+)?))\s*分\))?\s*$", 2));
|
||||
QuestionPatterns.Add(new RegexPatternConfig(@"^\(([一二三四五六七八九十]{1,2}|十[一二三四五六七八九])\)\s*(.+?)(?:\s*\(((\d+(?:\.\d+)?))\s*分\))?\s*$", 1));
|
||||
|
||||
|
||||
// 模式 1: "1. 这是一个题目 (5分)" 或 "1. 这是一个题目"
|
||||
QuestionPatterns.Add(new RegexPatternConfig(@"^(\d+)\.\s*(.+?)(?:\s*\(((\d+(?:\.\d+)?))\s*分\))?\s*$", 1));
|
||||
QuestionPatterns.Add(new RegexPatternConfig(@"^(\d+)\.\s*(.+?)(?:\s*\(((\d+(?:\.\d+)?))\s*分\))?\s*$", 2));
|
||||
|
||||
// 模式 2: "(1) 这是一个子题目 (3分)" 或 "(1) 这是一个子题目"
|
||||
QuestionPatterns.Add(new RegexPatternConfig(@"^\((\d+)\)\s*(.+?)(?:\s*\(((\d+(?:\.\d+)?))\s*分\))?\s*$", 2));
|
||||
QuestionPatterns.Add(new RegexPatternConfig(@"^\((\d+)\)\s*(.+?)(?:\s*\(((\d+(?:\.\d+)?))\s*分\))?\s*$", 3));
|
||||
|
||||
// 模式 3: "① 这是一个更深层次的子题目 (2分)" 或 "① 这是一个更深层次的子题目"
|
||||
QuestionPatterns.Add(new RegexPatternConfig(@"^[①②③④⑤⑥⑦⑧⑨⑩]+\s*(.+?)(?:\s*\(((\d+(?:\.\d+)?))\s*分\))?\s*$", 3));
|
||||
QuestionPatterns.Add(new RegexPatternConfig(@"^[①②③④⑤⑥⑦⑧⑨⑩]+\s*(.+?)(?:\s*\(((\d+(?:\.\d+)?))\s*分\))?\s*$", 4));
|
||||
|
||||
|
||||
OptionPatterns.Add(new RegexPatternConfig(@"([A-Z]\.)\s*(.*?)(?=[A-Z]\.|$)", 1)); // 大写字母选项
|
||||
@@ -251,6 +252,23 @@ namespace TechHelper.Client.Exam
|
||||
_config = config ?? throw new ArgumentNullException(nameof(config), "ExamParserConfig cannot be null.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// 一.基础
|
||||
/// 1.听写
|
||||
/// 2.阅读
|
||||
/// 二.提升
|
||||
/// 1.阅读
|
||||
/// (1).选择
|
||||
/// (2).填空
|
||||
/// 三.写
|
||||
/// (一)课文
|
||||
///
|
||||
///
|
||||
///
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Builds the ExamPaper structure from raw text and potential matches.
|
||||
/// Collects and returns parsing errors encountered during the process.
|
||||
@@ -260,7 +278,7 @@ namespace TechHelper.Client.Exam
|
||||
/// <returns>An ExamPaper object containing the parsed structure and a list of errors.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown if fullExamText is null or empty.</exception>
|
||||
/// <exception cref="ArgumentNullException">Thrown if allPotentialMatches is null.</exception>
|
||||
public ExamPaper BuildExamPaper(string fullExamText, List<PotentialMatch> allPotentialMatches)
|
||||
public ExamPaper BuildExam(string fullExamText, List<PotentialMatch> allPotentialMatches)
|
||||
{
|
||||
// 核心输入验证仍然是必要的,因为这些错误是无法恢复的
|
||||
if (string.IsNullOrWhiteSpace(fullExamText))
|
||||
@@ -289,8 +307,8 @@ namespace TechHelper.Client.Exam
|
||||
var majorQGStack = new Stack<MajorQuestionGroup>();
|
||||
MajorQuestionGroup currentMajorQG = null;
|
||||
|
||||
var questionStack = new Stack<Question>();
|
||||
Question currentQuestion = null;
|
||||
var questionStack = new Stack<PaperQuestion>();
|
||||
PaperQuestion currentQuestion = null;
|
||||
|
||||
int currentContentStart = 0;
|
||||
|
||||
@@ -388,6 +406,7 @@ namespace TechHelper.Client.Exam
|
||||
Title = pm.RegexMatch.Groups[2].Value.Trim(), // 标题是 Group 2
|
||||
Score = score,
|
||||
Priority = pm.PatternConfig.Priority,
|
||||
bGroup = true
|
||||
};
|
||||
|
||||
if (majorQGStack.Any())
|
||||
@@ -446,7 +465,7 @@ namespace TechHelper.Client.Exam
|
||||
}
|
||||
}
|
||||
|
||||
Question newQuestion = new Question
|
||||
PaperQuestion newQuestion = new PaperQuestion
|
||||
{
|
||||
Number = pm.RegexMatch.Groups[1].Value.Trim(),
|
||||
Stem = pm.RegexMatch.Groups[2].Value.Trim(),
|
||||
@@ -618,7 +637,7 @@ namespace TechHelper.Client.Exam
|
||||
/// Processes the content of a Question, mainly for parsing Options and identifying unstructured text.
|
||||
/// Logs errors to the provided error list instead of throwing.
|
||||
/// </summary>
|
||||
private void ProcessQuestionContent(Question question, string contentText, List<PotentialMatch> potentialMatchesInScope, List<ParseError> errors)
|
||||
private void ProcessQuestionContent(PaperQuestion question, string contentText, List<PotentialMatch> potentialMatchesInScope, List<ParseError> errors)
|
||||
{
|
||||
// 参数验证,这些是内部方法的契约,如果违反则直接抛出,因为这意味着调用者有错
|
||||
if (question == null) throw new ArgumentNullException(nameof(question), "Question cannot be null in ProcessQuestionContent.");
|
||||
@@ -674,8 +693,10 @@ namespace TechHelper.Client.Exam
|
||||
question.Options.Add(newOption);
|
||||
lastOptionEndIndex = pm.EndIndex;
|
||||
}
|
||||
// TODO: If there are SubQuestion types, they can be processed similarly here.
|
||||
// 你可以在此处添加对子问题的处理逻辑,同样需要小心处理其内容和嵌套。
|
||||
else
|
||||
{
|
||||
question.Stem += contentText;
|
||||
}
|
||||
}
|
||||
catch (Exception innerEx)
|
||||
{
|
||||
@@ -734,7 +755,7 @@ namespace TechHelper.Client.Exam
|
||||
// 2. 构建:根据扫描结果和原始文本,线性遍历并构建层级结构
|
||||
// BuildExamPaper 现在会返回一个包含错误列表的 ExamPaper 对象
|
||||
// 外部不再需要捕获内部解析异常,只需检查 ExamPaper.Errors 列表
|
||||
return _builder.BuildExamPaper(examPaperText, allPotentialMatches);
|
||||
return _builder.BuildExam(examPaperText, allPotentialMatches);
|
||||
}
|
||||
}
|
||||
}
|
@@ -52,7 +52,7 @@ namespace TechHelper.Client.Exam
|
||||
Title = dto.AssignmentTitle
|
||||
};
|
||||
|
||||
GetSeqRecursive(dto.QuestionGroups, null, examStruct.Questions);
|
||||
GetSeqRecursive(dto.ExamStruct, null, examStruct.Questions);
|
||||
|
||||
return examStruct;
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
@using Entities.DTO
|
||||
@using TechHelper.Client.Exam
|
||||
@using TechHelper.Client.Services
|
||||
@page "/exam/check/{ExamID}"
|
||||
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
@page "/exam/create"
|
||||
@using TechHelper.Client.Services
|
||||
@using Blazored.TextEditor
|
||||
@using Entities.DTO
|
||||
@using TechHelper.Client.Exam
|
||||
@@ -82,7 +83,7 @@
|
||||
}
|
||||
private BlazoredTextEditor _textEditor = new BlazoredTextEditor();
|
||||
private ExamPaper _parsedExam = new ExamPaper();
|
||||
private ExamDto ExamContent = new ExamDto();
|
||||
private AssignmentDto ExamContent = new AssignmentDto();
|
||||
|
||||
private ExamParserConfig _examParserConfig { get; set; } = new ExamParserConfig();
|
||||
|
||||
@@ -101,7 +102,7 @@
|
||||
Snackbar.Add("试卷解析成功。", Severity.Success);
|
||||
Snackbar.Add($"{_parsedExam.Errors}。", Severity.Success);
|
||||
ExamContent = _parsedExam.ConvertToExamDTO();
|
||||
ExamContent.SeqIndex();
|
||||
// ExamContent.SeqIndex();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -125,7 +126,6 @@
|
||||
|
||||
public async Task Publish()
|
||||
{
|
||||
ExamContent.CreaterEmail = authenticationStateTask.Result.User.Identity.Name;
|
||||
var apiRespon = await examService.SaveParsedExam(ExamContent);
|
||||
Snackbar.Add(apiRespon.Message);
|
||||
}
|
||||
|
@@ -1,5 +1,7 @@
|
||||
@page "/exam/edit/{ExamId}"
|
||||
@using Entities.DTO
|
||||
@using TechHelper.Client.Services
|
||||
@using Entities.DTO
|
||||
@using TechHelper.Client.Exam
|
||||
|
||||
<ExamView ParsedExam="@ExamDto"/>
|
||||
@@ -17,7 +19,7 @@
|
||||
[Inject]
|
||||
private ISnackbar Snackbar { get; set; }
|
||||
|
||||
private ExamDto ExamDto { get; set; }
|
||||
private AssignmentDto ExamDto { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
@@ -27,8 +29,8 @@
|
||||
Console.WriteLine($"ExamId 字符串成功解析为 Guid: {parsedExamId}");
|
||||
try
|
||||
{
|
||||
var result = await ExamService.GetExam(parsedExamId);
|
||||
if (result.Status) ExamDto = result.Result as ExamDto ?? new ExamDto();
|
||||
// var result = await ExamService.GetExam(parsedExamId);
|
||||
// if (result.Status) ExamDto = result.Result as ExamDto ?? new ExamDto();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@@ -4,41 +4,29 @@
|
||||
|
||||
<MudPaper Elevation=@Elevation Class=@Class>
|
||||
|
||||
@foreach (var majorQG in MajorQGList)
|
||||
{
|
||||
<MudStack Row="true">
|
||||
<MudText Typo="Typo.h6">@majorQG.Title</MudText>
|
||||
@if (majorQG.Score > 0)
|
||||
<MudStack Row="true">
|
||||
<MudText Typo="Typo.h6">@ExamStruct.Title</MudText>
|
||||
@if (ExamStruct.Score > 0)
|
||||
{
|
||||
<MudText Typo="Typo.body2"><b>总分:</b> @majorQG.Score 分</MudText>
|
||||
<MudText Typo="Typo.body2"><b>总分:</b> @ExamStruct.Score 分</MudText>
|
||||
}
|
||||
</MudStack>
|
||||
|
||||
@foreach (var childStruct in ExamStruct.ChildrenGroups)
|
||||
{
|
||||
<ExamGroupView ExamStruct="childStruct"/>
|
||||
}
|
||||
|
||||
@if (!string.IsNullOrWhiteSpace(majorQG.Descript))
|
||||
{
|
||||
<MudText Typo="Typo.body2">@((MarkupString)majorQG.Descript.Replace("\n", "<br />"))</MudText>
|
||||
}
|
||||
|
||||
@if (majorQG.SubQuestions.Any())
|
||||
{
|
||||
@foreach (var question in majorQG.SubQuestions)
|
||||
{
|
||||
<QuestionCard Question="question" Elevation=@Elevation Class="my-2 pa-1" />
|
||||
}
|
||||
}
|
||||
|
||||
@if (majorQG.SubQuestionGroups.Any())
|
||||
{
|
||||
<ExamGroupView MajorQGList="majorQG.SubQuestionGroups" Elevation="1" />
|
||||
}
|
||||
@foreach (var question in ExamStruct.AssignmentQuestions)
|
||||
{
|
||||
<QuestionCard Question="question.Question" Elevation=@Elevation Class="my-2 pa-1" />
|
||||
}
|
||||
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public List<QuestionGroupDto> MajorQGList { get; set; } = new List<QuestionGroupDto>();
|
||||
public AssignmentStructDto ExamStruct { get; set; } = new AssignmentStructDto();
|
||||
|
||||
[Parameter]
|
||||
public string Class { get; set; } = "my-2 pa-1";
|
||||
|
@@ -4,6 +4,8 @@
|
||||
|
||||
|
||||
@page "/exam/manage"
|
||||
@using Entities.DTO
|
||||
@using TechHelper.Client.Services
|
||||
@attribute [Authorize]
|
||||
|
||||
|
||||
|
@@ -5,10 +5,10 @@
|
||||
{
|
||||
|
||||
<MudPaper Height="@Height" Class="@Class" Style="@Style" Width="@Width">
|
||||
<MudText Class="d-flex justify-content-center" Typo="Typo.h6"> @ParsedExam.AssignmentTitle </MudText>
|
||||
<MudText Class="d-flex justify-content-center" Typo="Typo.h6"> @ParsedExam.Title </MudText>
|
||||
<MudText Typo="Typo.body1"> @ParsedExam.Description </MudText>
|
||||
|
||||
<ExamGroupView MajorQGList="@ParsedExam.QuestionGroups.SubQuestionGroups" Elevation="1" Class="ma-0 pa-2" />
|
||||
<ExamGroupView ExamStruct="@ParsedExam.ExamStruct" Elevation="1" Class="ma-0 pa-2" />
|
||||
</MudPaper>
|
||||
|
||||
}
|
||||
@@ -24,7 +24,7 @@ else
|
||||
@code {
|
||||
|
||||
[Parameter]
|
||||
public ExamDto ParsedExam { get; set; } = new ExamDto();
|
||||
public AssignmentDto ParsedExam { get; set; } = new AssignmentDto();
|
||||
[Parameter]
|
||||
public string Height { get; set; } = "100%";
|
||||
[Parameter]
|
||||
|
@@ -4,29 +4,35 @@
|
||||
<MudPaper Class=@Class Elevation=@Elevation Outlined="false">
|
||||
|
||||
<MudText Typo="Typo.subtitle1">
|
||||
<b>@Question.Index</b> @((MarkupString)Question.Stem.Replace("\n", "<br />"))
|
||||
<b>@Question.Index</b> @((MarkupString)Question.Title.Replace("\n", "<br />"))
|
||||
@if (Question.Score > 0)
|
||||
{
|
||||
<MudText Typo="Typo.body2" Class="d-inline ml-2">(@Question.Score 分)</MudText>
|
||||
}
|
||||
</MudText>
|
||||
|
||||
@if (Question.Options.Any())
|
||||
@if (Question.Options != null)
|
||||
{
|
||||
<div class="mt-2">
|
||||
@foreach (var option in Question.Options)
|
||||
@foreach (var option in Question.Options.ParseOptionsFromText())
|
||||
{
|
||||
var tempOption = option;
|
||||
<p>@((MarkupString)(tempOption.Value.Replace("\n", "<br />")))</p>
|
||||
<p>@((MarkupString)(tempOption.Replace("\n", "<br />")))</p>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
@foreach(var item in Question.ChildrenQuestion)
|
||||
{
|
||||
<QuestionCard Question="item"/>
|
||||
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public SubQuestionDto Question { get; set; } = new SubQuestionDto();
|
||||
public QuestionDto Question { get; set; } = new QuestionDto();
|
||||
|
||||
[Parameter]
|
||||
public string Class { get; set; }
|
||||
|
@@ -13,7 +13,6 @@ using TechHelper.Client.Services;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
|
||||
using TechHelper.Client.AI;
|
||||
using TechHelper.Client.Exam;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
|
||||
|
@@ -3,9 +3,9 @@ using TechHelper.Client.AI;
|
||||
using TechHelper.Services;
|
||||
using Entities.DTO;
|
||||
using System.Net.Http.Json; // 用于 PostAsJsonAsync
|
||||
using Newtonsoft.Json; // 用于 JSON 反序列化
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace TechHelper.Client.Exam
|
||||
namespace TechHelper.Client.Services
|
||||
{
|
||||
public class ExamService : IExamService
|
||||
{
|
||||
@@ -144,10 +144,10 @@ namespace TechHelper.Client.Exam
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ApiResponse> SaveParsedExam(ExamDto examDto)
|
||||
public async Task<ApiResponse> SaveParsedExam(AssignmentDto assiDto)
|
||||
{
|
||||
// 直接使用注入的 _client 实例
|
||||
var response = await _client.PostAsJsonAsync("exam/add", examDto);
|
||||
var response = await _client.PostAsJsonAsync("exam/add", assiDto);
|
||||
|
||||
if (response.IsSuccessStatusCode) // 检查是否是成功的状态码,例如 200 OK, 201 Created 等
|
||||
{
|
@@ -1,13 +1,13 @@
|
||||
using Entities.DTO;
|
||||
using TechHelper.Services;
|
||||
|
||||
namespace TechHelper.Client.Exam
|
||||
namespace TechHelper.Client.Services
|
||||
{
|
||||
public interface IExamService
|
||||
{
|
||||
public Task<ApiResponse> FormatExam(string examContent);
|
||||
public Task<ApiResponse> DividExam(string examContent);
|
||||
public Task<ApiResponse> SaveParsedExam(ExamDto examDto);
|
||||
public Task<ApiResponse> SaveParsedExam(AssignmentDto assiDto);
|
||||
public Task<ApiResponse> ParseSingleQuestionGroup(string examContent);
|
||||
public ApiResponse ConvertToXML<T>(string xmlContent);
|
||||
|
@@ -22,6 +22,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper" Version="14.0.0" />
|
||||
<PackageReference Include="Blazor.LocalStorage.WebAssembly" Version="8.0.0" />
|
||||
<PackageReference Include="Blazored.TextEditor" Version="1.1.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.12" />
|
||||
|
Reference in New Issue
Block a user