This commit is contained in:
SpecialX
2025-06-27 19:03:10 +08:00
parent 14fbe6397a
commit a21ca80782
57 changed files with 3872 additions and 611 deletions

View File

@@ -15,6 +15,9 @@ namespace TechHelper.Context
CreateMap<AssignmentQuestionEx, AssignmentQuestionDto>()
.ForMember(d=>d.Description, o=>o.Ignore());
CreateMap<AssignmentEx, AssignmentDto>();
CreateMap<AssignmentCheckData, Submission>();
}
}

View File

@@ -2,18 +2,20 @@
namespace TechHelper.Client.Exam
{
public class ExamStruct
public class AssignmentCheckData
{
public string Title { get; set; }
public List<QuestionItem> Questions { get; set; } = new List<QuestionItem>();
public string Title { get; set; }
public Guid AssignmentId { get; set; }
public Guid StudentId { get; set; }
public List<AssignmentCheckQuestion> Questions { get; set; } = new List<AssignmentCheckQuestion>();
}
public class QuestionItem
{
public string Sequence { get; set; } = string.Empty;
public string QuestionText { get; set; } = string.Empty;
public float Score { get; set; }
}
public class AssignmentCheckQuestion
{
public string Sequence { get; set; } = string.Empty;
public AssignmentQuestionDto AssignmentQuestionDto { get; set; } = new AssignmentQuestionDto();
public float Score { get; set; }
}
public class Student
@@ -24,32 +26,32 @@ namespace TechHelper.Client.Exam
public class QuestionAnswerStatus
{
public string QuestionSequence { get; set; } = string.Empty; // 题目序号,例如 "1.1"
public string QuestionText { get; set; } = string.Empty; // 题目文本
public float QuestionScore { get; set; } // 题目分值
public string QuestionSequence { get; set; } = string.Empty; // 题目序号,例如 "1.1"
public string QuestionText { get; set; } = string.Empty; // 题目文本
public float QuestionScore { get; set; } // 题目分值
public Dictionary<Guid, bool> StudentCorrectStatus { get; set; } = new Dictionary<Guid, bool>();
// Key: Student.Id, Value: true 表示正确false 表示错误
}
public class QuestionRowData
{
public ExamStruct.QuestionItem QuestionItem { get; set; } // 原始题目信息
public AssignmentCheckQuestion QuestionItem { get; set; } // 原始题目信息
public Dictionary<Guid, bool> StudentAnswers { get; set; } = new Dictionary<Guid, bool>();
}
public static class ExamStructExtensions
{
public static ExamStruct GetStruct(this AssignmentDto dto)
public static AssignmentCheckData GetStruct(this AssignmentDto dto)
{
if (dto == null)
{
return new ExamStruct { Title = "无效试卷", Questions = new List<ExamStruct.QuestionItem>() };
return new AssignmentCheckData { Title = "无效试卷", Questions = new List<AssignmentCheckQuestion>() };
}
var examStruct = new ExamStruct
var examStruct = new AssignmentCheckData
{
Title = dto.Title
Title = dto.Title
};
GetSeqRecursive(dto.ExamStruct, null, examStruct.Questions);
@@ -65,8 +67,8 @@ namespace TechHelper.Client.Exam
/// <param name="allQuestions">用于收集所有生成题目项的列表。</param>
private static void GetSeqRecursive(
AssignmentQuestionDto currentGroup,
string? parentSequence,
List<ExamStruct.QuestionItem> allQuestions)
string? parentSequence,
List<AssignmentCheckQuestion> allQuestions)
{
string currentGroupSequence = parentSequence != null
? $"{parentSequence}.{currentGroup.Index}"
@@ -76,6 +78,17 @@ namespace TechHelper.Client.Exam
{
GetSeqRecursive(subGroup, currentGroupSequence, allQuestions);
}
if (!string.IsNullOrEmpty(currentGroup.Sequence))
{
allQuestions.Add(new AssignmentCheckQuestion
{
AssignmentQuestionDto = currentGroup,
//Sequence = currentGroupSequence,
Sequence = currentGroup.Sequence,
Score = currentGroup.Score,
});
}
}
}
}

View File

@@ -7,7 +7,7 @@ using AutoMapper;
namespace TechHelper.Client.Exam
{
public static class ExamPaperExtensions
public static class AssignmentExtensions
{
public static List<string> ParseOptionsFromText(this string optionsText)
@@ -25,9 +25,9 @@ namespace TechHelper.Client.Exam
public static void SeqQGroupIndex(this AssignmentQuestionDto dto)
{
foreach(var sqg in dto.ChildrenAssignmentQuestion)
foreach (var sqg in dto.ChildrenAssignmentQuestion)
{
sqg.Index = (byte)dto.ChildrenAssignmentQuestion.IndexOf(sqg);
sqg.Index = (byte)(dto.ChildrenAssignmentQuestion.IndexOf(sqg) + 1);
sqg.SeqQGroupIndex();
}

View File

@@ -56,6 +56,7 @@ namespace TechHelper.Client.Exam
public string Description { get; set; } = string.Empty;
public byte Index { get; set; } = 0;
public float Score { get; set; }
public string Sequence { get; set; } = string.Empty;
public QuestionEx? Question { get; set; }
public AssignmentStructType Type { get; set; }
public List<AssignmentQuestionEx> ChildrenAssignmentQuestion { get; set; } = new List<AssignmentQuestionEx>();
@@ -344,6 +345,8 @@ namespace TechHelper.Client.Exam
assignmentQuestionStack.Pop();
}
string sequence = assignmentQuestionStack.Count > 0 ? assignmentQuestionStack.Peek().Sequence : string.Empty;
// 验证捕获组Group 1 是编号Group 2 是题目内容
if (pm.RegexMatch.Groups.Count < 3 || !pm.RegexMatch.Groups[1].Success || string.IsNullOrWhiteSpace(pm.RegexMatch.Groups[2].Value))
{
@@ -372,6 +375,8 @@ namespace TechHelper.Client.Exam
// 提取标题,这里使用 Group 2 的值,它不包含分数
string title = pm.RegexMatch.Groups[2].Value.Trim();
string seq = pm.RegexMatch.Groups[1].Value.Trim();
seq = string.IsNullOrEmpty(seq) || string.IsNullOrEmpty(sequence) ? seq : " ." + seq;
AssignmentQuestionEx newAssignmentQuestion;
if (pm.PatternConfig.Type == AssignmentStructType.Struct)
@@ -380,6 +385,7 @@ namespace TechHelper.Client.Exam
{
Title = title,
Score = score,
Sequence = sequence + seq,
Priority = pm.PatternConfig.Priority,
Type = pm.PatternConfig.Type
};
@@ -390,6 +396,7 @@ namespace TechHelper.Client.Exam
{
Priority = pm.PatternConfig.Priority,
Type = pm.PatternConfig.Type,
Sequence = sequence + seq,
Score = score,
Question = new QuestionEx
{

View File

@@ -92,7 +92,6 @@ namespace TechHelper.Client.HttpRepository
public async Task<ResponseDto> RegisterUserAsync(UserForRegistrationDto userForRegistrationDto)
{
// 移除 using (_client = _clientFactory.CreateClient("Default"))
userForRegistrationDto.ClientURI = Path.Combine(
_navigationManager.BaseUri, "emailconfirmation");

View File

@@ -9,216 +9,227 @@
@if (_isLoading)
{
<MudProgressCircular Indeterminate="true" Color="Color.Primary" Class="d-flex justify-center my-8" />
<MudText Class="text-center">正在加载试卷和学生数据...</MudText>
<MudProgressCircular Indeterminate="true" Color="Color.Primary" Class="d-flex justify-center my-8" />
<MudText Class="text-center">正在加载试卷和学生数据...</MudText>
}
else if (_questionsForTable.Any() && _students.Any())
{
<MudTable @ref="_table" T="QuestionRowData" Items="@_questionsForTable" Hover="true" Breakpoint="Breakpoint.Sm" Class="mud-elevation-2" Dense="true">
<HeaderContent>
<MudTh Style="width:100px;">序号</MudTh>
<MudTh Style="width:80px; text-align:center;">分值</MudTh>
@foreach (var student in _students)
{
<MudTh Style="width:120px; text-align:center;">
@student.Name
<MudTooltip Text="点击以切换此学生所有题目的对错">
<MudIconButton Icon="@Icons.Material.Filled.Info" Size="Size.Small" Class="ml-1"
@onclick="() => ToggleStudentAllAnswers(student.Id)" />
</MudTooltip>
</MudTh>
}
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="序号">@context.QuestionItem.Sequence</MudTd>
<MudTd DataLabel="分值" Style="text-align:center;">@context.QuestionItem.Score</MudTd>
@foreach (var student in _students)
{
<MudTd DataLabel="@student.Name" Style="text-align:center;">
@if (context.StudentAnswers.ContainsKey(student.Id))
{
<MudCheckBox @bind-Value="context.StudentAnswers[student.Id]" Size="Size.Small" Color="Color.Primary"></MudCheckBox>
}
else
{
<MudText Color="Color.Warning">N/A</MudText>
}
</MudTd>
}
</RowTemplate>
<PagerContent>
<MudTablePager />
</PagerContent>
</MudTable>
<MudTable @ref="_table" T="QuestionRowData" Items="@_questionsForTable" Hover="true" Breakpoint="Breakpoint.Sm" Striped="true" Class="mud-elevation-2" Dense="true">
<HeaderContent>
<MudTh Style="width:100px;">序号</MudTh>
<MudTh Style="width:80px; text-align:center;">分值</MudTh>
@foreach (var student in _students)
{
<MudTh Style="width:120px; text-align:center;">
@student.DisplayName
<MudTooltip Text="点击以切换此学生所有题目的对错">
<MudIconButton Icon="@Icons.Material.Filled.Info" Size="Size.Small" Class="ml-1"
@onclick="() => ToggleStudentAllAnswers(student.Id)" />
</MudTooltip>
</MudTh>
}
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="序号">@context.QuestionItem.Sequence</MudTd>
<MudTd DataLabel="分值" Style="text-align:center;">@context.QuestionItem.Score</MudTd>
@foreach (var student in _students)
{
<MudTd DataLabel="@student.DisplayName" Style="text-align:center;">
@if (context.StudentAnswers.ContainsKey(student.Id))
{
<MudCheckBox @bind-Value="context.StudentAnswers[student.Id]" Size="Size.Small" Color="Color.Primary"></MudCheckBox>
}
else
{
<MudText Color="Color.Warning">N/A</MudText>
}
</MudTd>
}
</RowTemplate>
<PagerContent>
<MudTablePager />
</PagerContent>
</MudTable>
<MudPaper Class="pa-4 mt-4 mud-elevation-2 d-flex flex-column align-end">
<MudText Typo="Typo.h6">学生总分预览:</MudText>
@foreach (var student in _students)
{
<MudText Typo="Typo.subtitle1">
@student.Name: <MudText Typo="Typo.h5" Color="Color.Primary" Class="d-inline-block ml-2">@GetStudentTotalScore(student.Id)</MudText>
</MudText>
}
<MudButton Variant="Variant.Filled" Color="Color.Success" Class="mt-4" @onclick="SubmitGrading">
提交批改结果 (模拟)
</MudButton>
</MudPaper>
<MudPaper Class="pa-4 mt-4 mud-elevation-2 d-flex flex-column align-end">
<MudText Typo="Typo.h6">学生总分预览:</MudText>
@foreach (var student in _students)
{
<MudText Typo="Typo.subtitle1">
@student.DisplayName: <MudText Typo="Typo.h5" Color="Color.Primary" Class="d-inline-block ml-2">@GetStudentTotalScore(student.Id)</MudText>
</MudText>
}
<MudButton Variant="Variant.Filled" Color="Color.Success" Class="mt-4" @onclick="SubmitGrading">
提交批改结果 (模拟)
</MudButton>
</MudPaper>
}
else
{
<MudAlert Severity="Severity.Info" Class="mt-4">无法加载试卷或题目信息。</MudAlert>
<MudButton Variant="Variant.Text" Color="Color.Primary" Class="mt-4" >返回试卷列表</MudButton>
<MudAlert Severity="Severity.Info" Class="mt-4">无法加载试卷或题目信息。</MudAlert>
<MudButton Variant="Variant.Text" Color="Color.Primary" Class="mt-4">返回试卷列表</MudButton>
}
@code {
[Parameter]
public string ExamId { get; set; }
[Parameter]
public string ExamId { get; set; }
[Inject]
public IExamService ExamService { get; set; }
[Inject]
public IExamService ExamService { get; set; }
[Inject]
private ISnackbar Snackbar { get; set; }
[Inject]
private ISnackbar Snackbar { get; set; }
[Inject]
private NavigationManager Navigation { get; set; }
[Inject]
private NavigationManager Navigation { get; set; }
private MudTable<QuestionRowData> _table = new();
private AssignmentDto Assignment { get; set; } = new AssignmentDto();
private ExamStruct _examStruct = new ExamStruct();
private MudTable<QuestionRowData> _table = new();
private AssignmentDto Assignment { get; set; } = new AssignmentDto();
private AssignmentCheckData _examStruct = new AssignmentCheckData();
private List<Student> _students = new List<Student>();
private List<QuestionRowData> _questionsForTable = new List<QuestionRowData>();
private List<StudentDto> _students = new List<StudentDto>();
private List<QuestionRowData> _questionsForTable = new List<QuestionRowData>();
private bool _isLoading = true;
private bool _isLoading = true;
[Inject]
public IClassServices ClassServices { get; set; }
protected override async Task OnInitializedAsync()
{
_isLoading = true;
await LoadExamData();
var result = await ClassServices.GetClassStudents();
if (!result.Status) Snackbar.Add($"获取学生失败, {result.Message}", Severity.Error);
_students = result.Result as List<StudentDto> ?? new List<StudentDto>();
BuildTable();
_isLoading = false;
}
private void BuildTable()
{
_questionsForTable = _examStruct.Questions.Select(q =>
{
var rowData = new QuestionRowData
{
QuestionItem = q,
StudentAnswers = new Dictionary<Guid, bool>()
};
foreach (var student in _students)
{
rowData.StudentAnswers[student.Id] = false;
}
return rowData;
}).ToList();
}
private async Task LoadExamData()
{
if (Guid.TryParse(ExamId, out Guid parsedExamId))
{
try
{
var result = await ExamService.GetExam(parsedExamId);
if (result.Status)
{
Assignment = result.Result as AssignmentDto ?? new AssignmentDto();
_examStruct = Assignment.GetStruct();
}
else
{
Snackbar?.Add($"获取试卷失败: {result.Message}", Severity.Error);
Navigation.NavigateTo("/exam/manager");
}
}
catch (Exception ex)
{
Console.Error.WriteLine($"获取试卷时发生错误: {ex.Message}");
Snackbar?.Add($"获取试卷失败: {ex.Message}", Severity.Error);
Navigation.NavigateTo("/exam/manager");
}
}
else
{
Console.Error.WriteLine($"错误:路由参数 ExamId '{ExamId}' 不是一个有效的 GUID 格式。");
Snackbar?.Add("无效的试卷ID无法加载。", Severity.Error);
Navigation.NavigateTo("/exam/manager");
}
}
protected override async Task OnInitializedAsync()
{
_isLoading = true;
await LoadExamData();
GenerateTemporaryStudentsAndAnswers();
_isLoading = false;
}
private float GetStudentTotalScore(Guid studentId)
{
float totalScore = 0;
foreach (var row in _questionsForTable)
{
if (row.StudentAnswers.TryGetValue(studentId, out bool isCorrect) && isCorrect)
{
totalScore += row.QuestionItem.Score;
}
}
return totalScore;
}
private void ToggleStudentAllAnswers(Guid studentId)
{
bool allCorrect = _questionsForTable.All(row => row.StudentAnswers.ContainsKey(studentId) && row.StudentAnswers[studentId]);
foreach (var row in _questionsForTable)
{
if (row.StudentAnswers.ContainsKey(studentId))
{
row.StudentAnswers[studentId] = !allCorrect;
}
}
StateHasChanged();
}
private void SubmitGrading()
{
List<SubmissionDto> submissionDto = new List<SubmissionDto>();
private async Task LoadExamData()
{
if (Guid.TryParse(ExamId, out Guid parsedExamId))
{
try
{
var result = await ExamService.GetExam(parsedExamId);
if (result.Status)
{
Assignment = result.Result as AssignmentDto ?? new AssignmentDto();
_examStruct = Assignment.GetStruct();
}
else
{
Snackbar?.Add($"获取试卷失败: {result.Message}", Severity.Error);
Navigation.NavigateTo("/exam/manager");
}
}
catch (Exception ex)
{
Console.Error.WriteLine($"获取试卷时发生错误: {ex.Message}");
Snackbar?.Add($"获取试卷失败: {ex.Message}", Severity.Error);
Navigation.NavigateTo("/exam/manager");
}
}
else
{
Console.Error.WriteLine($"错误:路由参数 ExamId '{ExamId}' 不是一个有效的 GUID 格式。");
Snackbar?.Add("无效的试卷ID无法加载。", Severity.Error);
Navigation.NavigateTo("/exam/manager");
}
}
foreach (var student in _students)
{
var newSubmission = new SubmissionDto();
newSubmission.StudentId = student.Id;
newSubmission.AssignmentId = Assignment.Id;
newSubmission.SubmissionTime = DateTime.Now;
newSubmission.Status = Entities.Contracts.SubmissionStatus.Submitted;
// 生成临时学生和作答数据
private void GenerateTemporaryStudentsAndAnswers()
{
_students = new List<Student>();
// 生成 40 个学生
for (int i = 1; i <= 40; i++)
{
_students.Add(new Student { Name = $"学生{i}" });
}
_questionsForTable = _examStruct.Questions.Select(qItem =>
{
var rowData = new QuestionRowData
{
QuestionItem = qItem,
StudentAnswers = new Dictionary<Guid, bool>()
};
foreach (var row in _questionsForTable)
{
if (row.QuestionItem.AssignmentQuestionDto.StructType == Entities.Contracts.AssignmentStructType.Struct) continue;
if (row.StudentAnswers.TryGetValue(student.Id, out bool isCorrect))
{
newSubmission.SubmissionDetails.Add(new SubmissionDetailDto
{
IsCorrect = isCorrect,
StudentId = student.Id,
AssignmentQuestionId = row.QuestionItem.AssignmentQuestionDto.Id,
PointsAwarded = isCorrect ? row.QuestionItem.AssignmentQuestionDto.Score : 0
});
// 为每个学生随机生成初始的对错状态
var random = new Random();
foreach (var student in _students)
{
// 模拟随机对错50%的概率
rowData.StudentAnswers[student.Id] = random.Next(0, 2) == 1;
}
return rowData;
}).ToList();
}
newSubmission.OverallGrade += isCorrect ? row.QuestionItem.AssignmentQuestionDto.Score : 0;
}
}
submissionDto.Add(newSubmission);
}
// 当某个学生的某个题目的作答状态改变时触发
private void OnAnswerChanged(string questionSequence, Guid studentId, bool isCorrect)
{
// 可以在这里添加额外的逻辑,例如记录更改
Console.WriteLine($"题目 {questionSequence}, 学生 {studentId} 的答案变为: {isCorrect}");
// 由于是 @bind-Checked数据模型已经自动更新这里只是日志
}
submissionDto.ForEach(async s =>
{
Snackbar?.Add($"正在提交: {_students.FirstOrDefault(std => std.Id == s.StudentId)?.DisplayName} 的试卷", Severity.Info);
await ExamService.SubmissionAssignment(s);
});
// 计算某个学生的总分
private float GetStudentTotalScore(Guid studentId)
{
float totalScore = 0;
foreach (var row in _questionsForTable)
{
if (row.StudentAnswers.TryGetValue(studentId, out bool isCorrect) && isCorrect)
{
totalScore += row.QuestionItem.Score;
}
}
return totalScore;
}
// 切换某个学生所有题目的对错状态 (用于快速批改)
private void ToggleStudentAllAnswers(Guid studentId)
{
bool allCorrect = _questionsForTable.All(row => row.StudentAnswers.ContainsKey(studentId) && row.StudentAnswers[studentId]);
foreach (var row in _questionsForTable)
{
if (row.StudentAnswers.ContainsKey(studentId))
{
row.StudentAnswers[studentId] = !allCorrect; // 全部取反
}
}
StateHasChanged(); // 手动通知 Blazor 刷新 UI
}
// 提交批改结果(模拟)
private void SubmitGrading()
{
Console.WriteLine("--- 提交批改结果 ---");
foreach (var student in _students)
{
Console.WriteLine($"学生: {student.Name}, 总分: {GetStudentTotalScore(student.Id)}");
foreach (var row in _questionsForTable)
{
if (row.StudentAnswers.TryGetValue(student.Id, out bool isCorrect))
{
Console.WriteLine($" - 题目 {row.QuestionItem.Sequence}: {(isCorrect ? "正确" : "错误")}");
}
}
}
Snackbar?.Add("批改结果已提交(模拟)", Severity.Success);
// 实际应用中,这里会将 _questionsForTable 和 _students 的数据发送到后端API
}
Snackbar?.Add("批改结果已提交(模拟)", Severity.Success);
}
}

View File

@@ -49,7 +49,7 @@ else
{
isloding = true;
Snackbar.Add("正在加载", Severity.Info);
var result = await ExamService.GetAllExam(authenticationStateTask.Result.User.Identity.Name);
var result = await ExamService.GetAllExam();
examDtos = result.Result as List<AssignmentDto> ?? new List<AssignmentDto>();
isloding = false;
Snackbar.Add("加载成功", Severity.Info);

View File

@@ -12,7 +12,11 @@
<MudButton OnClick="ExamClick"> 详情 </MudButton>
<MudIconButton Icon="@Icons.Material.Filled.Delete" aria-label="delete" />
<MudIconButton Icon="@Icons.Custom.Brands.GitHub" OnClick="CheckExam" Color="Color.Primary" aria-label="github" />
@if (bteacher)
{
<MudIconButton Icon="@Icons.Material.Filled.Check" OnClick="CheckExam" Color="Color.Primary" aria-label="github" />
}
<MudIconButton Icon="@Icons.Material.Filled.Favorite" Color="Color.Secondary" aria-label="add to favorite" />
</MudButtonGroup>
</MudPaper>
@@ -21,6 +25,10 @@
</MudPaper>
@code {
[CascadingParameter]
private Task<AuthenticationState> authenticationStateTask { get; set; }
private bool bteacher = false;
[Inject]
public NavigationManager navigationManager { get; set; }
@@ -45,6 +53,12 @@
public string? MaxHeight { get; set; } = "64";
protected override Task OnInitializedAsync()
{
bteacher = authenticationStateTask.Result.User.IsInRole("Teacher");
return base.OnInitializedAsync();
}
private void ExamClick()
{
navigationManager.NavigateTo($"exam/edit/{AssignmentDto.Id}");

View File

@@ -1,118 +1,10 @@
@page "/"
@using Microsoft.AspNetCore.Authorization
<AuthorizeView Roles="Administrator">
<TechHelper.Client.Pages.Teacher.StudentsView/>
<MudText> Hello @context.User.Identity.Name</MudText>
@foreach (var item in context.User.Claims)
{
<MudPaper class="ma-2 pa-2">
<MudText> @item.Value </MudText>
<MudText> @item.Issuer </MudText>
<MudText> @item.Subject </MudText>
<MudText> @item.Properties </MudText>
<MudText> @item.ValueType </MudText>
</MudPaper>
}
Welcome to your new app.
</AuthorizeView>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
<MudText>Hello </MudText>
@code {
[CascadingParameter]
private Task<AuthenticationState> authenticationStateTask { get; set; }
}

View File

@@ -0,0 +1,28 @@
@using Entities.Contracts
@using Entities.DTO
@using TechHelper.Client.Services
<h3>StudentsView</h3>
@foreach(var cs in ClassStudents)
{
<MudText> @cs.DisplayName </MudText>
}
@code {
[CascadingParameter]
private Task<AuthenticationState> authenticationStateTask { get; set; }
private List<StudentDto> ClassStudents { get; set; } = new List<StudentDto>();
[Inject]
public IClassServices ClassServices { get; set; }
protected override async Task OnInitializedAsync()
{
var result = await ClassServices.GetClassStudents();
ClassStudents = result.Result as List<StudentDto> ?? new List<StudentDto>();
StateHasChanged();
}
}

View File

@@ -1,6 +1,9 @@
using Entities.DTO;
using Entities.Contracts;
using Entities.DTO;
using Newtonsoft.Json;
using System.Net.Http.Json;
using TechHelper.Client.HttpRepository;
using TechHelper.Services;
namespace TechHelper.Client.Services
{
@@ -20,6 +23,21 @@ namespace TechHelper.Client.Services
throw new NotImplementedException();
}
public async Task<ApiResponse> GetClassStudents()
{
try
{
var result = await _client.PostAsJsonAsync("class/getClassStudents","");
var content = await result.Content.ReadAsStringAsync();
var users = JsonConvert.DeserializeObject<List<StudentDto>>(content);
return ApiResponse.Success(result: users);
}
catch(Exception ex)
{
return ApiResponse.Error($"获取失败,{ex.Message}, InnerException: {ex.InnerException}");
}
}
public async Task<ResponseDto> UserRegister(UserRegistrationToClassDto userRegistrationToClassDto)
{
try

View File

@@ -9,13 +9,13 @@ namespace TechHelper.Client.Services
{
public class ExamService : IExamService
{
private readonly IAIService _aIService;
private readonly HttpClient _client;
private readonly IAIService _aIService;
private readonly HttpClient _client;
public ExamService(IAIService aIService, HttpClient client)
public ExamService(IAIService aIService, HttpClient client)
{
_aIService = aIService;
_client = client;
_client = client;
}
public ApiResponse ConvertToXML<T>(string xmlContent)
@@ -86,9 +86,9 @@ namespace TechHelper.Client.Services
}
}
public async Task<ApiResponse> GetAllExam(string user)
public async Task<ApiResponse> GetAllExam()
{
var response = await _client.GetAsync($"exam/getAllPreview?user={user}");
var response = await _client.GetAsync($"exam/getAllPreview");
if (response.IsSuccessStatusCode)
{
@@ -104,6 +104,25 @@ namespace TechHelper.Client.Services
}
}
public async Task<ApiResponse> GetAllSubmission()
{
try
{
var response = await _client.GetAsync($"exam/getAllSubmission");
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
var exam = JsonConvert.DeserializeObject<AssignmentDto>(content);
return ApiResponse.Success();
}
return ApiResponse.Error(message: "获取失败");
}
catch (Exception ex)
{
return ApiResponse.Error(message: $"内部错误{ex.Message}, InerEx{ex.InnerException}");
}
}
public async Task<ApiResponse> GetExam(Guid guid)
{
@@ -158,5 +177,18 @@ namespace TechHelper.Client.Services
return ApiResponse.Error(message: $"保存试题失败: {response.StatusCode} - {errorContent}");
}
}
public async Task<ApiResponse> SubmissionAssignment(SubmissionDto submission)
{
var response = await _client.PostAsJsonAsync("exam/submission", submission);
if (response.IsSuccessStatusCode)
{
return ApiResponse.Success("提交成功");
}
else
{
return ApiResponse.Error("提交失败");
}
}
}
}

View File

@@ -8,5 +8,6 @@ namespace TechHelper.Client.Services
{
public Task<ResponseDto> UserRegister(UserRegistrationToClassDto userRegistrationToClassDto);
public Task<ResponseDto> CreateClass(UserRegistrationToClassDto userClass);
public Task<ApiResponse> GetClassStudents();
}
}

View File

@@ -11,7 +11,9 @@ namespace TechHelper.Client.Services
public Task<ApiResponse> ParseSingleQuestionGroup(string examContent);
public ApiResponse ConvertToXML<T>(string xmlContent);
public Task<ApiResponse> GetAllExam(string user);
public Task<ApiResponse> GetAllExam();
public Task<ApiResponse> GetExam(Guid guid);
public Task<ApiResponse> SubmissionAssignment(SubmissionDto submission);
public Task<ApiResponse> GetAllSubmission();
}
}