添加项目文件。

This commit is contained in:
SpecialX
2025-05-23 19:03:00 +08:00
parent 6fa7679fd3
commit d36fef2bbb
185 changed files with 13413 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
@page "/emailconfirmation"
<h3>EmailConfirmation</h3>
<MudButton OnClick="ConfirmToEmail"> 点击确认 </MudButton>
<MudPaper>
@if (_showSuccess)
{
<h3> Successful </h3>
}
</MudPaper>

View File

@@ -0,0 +1,42 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.WebUtilities;
using System.Net;
using TechHelper.Client.HttpRepository;
namespace TechHelper.Client.Pages.Author
{
public partial class EmailConfirmation
{
private bool _showSuccess;
private bool _showError;
[Inject]
public IAuthenticationClientService AuthenticationClientService { get; set; }
[Inject]
public NavigationManager NavigationManager { get; set; }
protected async void ConfirmToEmail()
{
_showError = _showSuccess = false;
var uri = NavigationManager.ToAbsoluteUri(NavigationManager.Uri);
var queryStrings = QueryHelpers.ParseQuery(uri.Query);
if (queryStrings.TryGetValue("email", out var email) &&
queryStrings.TryGetValue("token", out var token))
{
var result = await AuthenticationClientService.EmailConfirmationAsync(email, token);
if (result == HttpStatusCode.OK)
_showSuccess = true;
else
_showError = true;
}
else
NavigationManager.NavigateTo("/");
}
}
}

View File

@@ -0,0 +1,38 @@
@page "/forgotpassword"
<EditForm Model="@_forgotPassDto" OnValidSubmit="Submit" FormName="ForgotForm">
<DataAnnotationsValidator />
<MudGrid>
<MudItem xs="12" sm="7">
<MudCard>
<MudCardContent>
<MudTextField Label="Email" Class="mt-3"
@bind-Value="_forgotPassDto.Email" For="@(() => _forgotPassDto.Email)" />
</MudCardContent>
<MudCardActions>
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" Color="Color.Primary" Class="ml-auto">Register</MudButton>
</MudCardActions>
</MudCard>
</MudItem>
<MudItem xs="12" sm="5">
<MudPaper Class="pa-4 mud-height-full">
<MudText Typo="Typo.subtitle2">Validation Summary</MudText>
@if (_showSuccess)
{
<MudText Color="Color.Success">Success</MudText>
}
else if(_showError)
{
<MudText Color="@Color.Error">
<ValidationSummary />
</MudText>
}
</MudPaper>
</MudItem>
<MudItem xs="12">
<MudText Typo="Typo.body2" Align="Align.Center">
Fill out the form correctly to see the success message.
</MudText>
</MudItem>
</MudGrid>
</EditForm>

View File

@@ -0,0 +1,30 @@
using Entities.DTO;
using Microsoft.AspNetCore.Components;
using TechHelper.Client.HttpRepository;
namespace TechHelper.Client.Pages.Author
{
public partial class ForgotPassword
{
private ForgotPasswordDto _forgotPassDto = new ForgotPasswordDto();
private bool _showSuccess;
private bool _showError;
[Inject]
public IAuthenticationClientService AuthenticationClientService { get; set; }
private async Task Submit()
{
_showError = _showSuccess = false;
var result = await AuthenticationClientService.ForgotPasswordAsync(_forgotPassDto);
if (result == System.Net.HttpStatusCode.OK)
{
_showSuccess = true;
}
_showError = true;
}
}
}

View File

@@ -0,0 +1,48 @@
@page "/login"
<MudText Typo="Typo.h2"> Login Account </MudText>
<EditForm Model="@_userForAuth" OnValidSubmit="Logining" FormName="LoginingForm">
<DataAnnotationsValidator />
<MudGrid>
<MudItem xs="12" sm="7">
<MudCard>
<MudCardContent>
<MudTextField Label="Email" Class="mt-3"
@bind-Value="_userForAuth.Email" For="@(() => _userForAuth.Email)" />
<MudTextField Label="Password" HelperText="Choose a strong password" Class="mt-3"
@bind-Value="_userForAuth.Password" For="@(() => _userForAuth.Password)" InputType="InputType.Password" />
</MudCardContent>
<MudCardActions>
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" Color="Color.Primary" Class="ml-auto">Register</MudButton>
</MudCardActions>
<div class="nav-item px-3">
<NavLink class="nav-link" href="forgotpassword">
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span>Forgot Password
</NavLink>
</div>
</MudCard>
</MudItem>
<MudItem xs="12" sm="5">
<MudPaper Class="pa-4 mud-height-full">
<MudText Typo="Typo.subtitle2">Validation Summary</MudText>
@if (!ShowRegistrationErrors)
{
<MudText Color="Color.Success">Success</MudText>
}
else
{
<MudText Color="@Color.Error">
<ValidationSummary />
</MudText>
}
</MudPaper>
</MudItem>
<MudItem xs="12">
<MudText Typo="Typo.body2" Align="Align.Center">
Fill out the form correctly to see the success message.
</MudText>
</MudItem>
</MudGrid>
</EditForm>

View File

@@ -0,0 +1,51 @@
using TechHelper.Client.HttpRepository;
using Entities.DTO;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.WebUtilities;
namespace TechHelper.Client.Pages.Author
{
public partial class Login
{
private UserForAuthenticationDto _userForAuth = new UserForAuthenticationDto();
[Inject]
public IAuthenticationClientService AuthenticationService { get; set; }
[Inject]
public NavigationManager NavigationManager { get; set; }
public bool ShowRegistrationErrors { get; set; }
public string Error { get; set; }
public async Task Logining()
{
ShowRegistrationErrors = false;
var result = await AuthenticationService.LoginAsync(_userForAuth);
if (result.Is2StepVerificationRequired)
{
var queryParams = new Dictionary<string, object?>
{
["provider"] = result.Provider,
["Email"] = _userForAuth.Email
};
var uri = NavigationManager.GetUriWithQueryParameters("/twostepverification", queryParams);
NavigationManager.NavigateTo(uri);
}
else if (!result.IsAuthSuccessful)
{
Error = result.ErrorMessage;
ShowRegistrationErrors = true;
}
else
{
NavigationManager.NavigateTo("/");
}
}
}
}

View File

@@ -0,0 +1,100 @@
@page "/register"
@using System.ComponentModel.DataAnnotations
@using Entities.Contracts
@inject ISnackbar Snackbar
<MudButton Variant="Variant.Filled" Color="Color.Primary" @onclick="@(() => Snackbar.Add("Simple Snackbar"))">
Open Snackbar
</MudButton>
<MudText Typo="Typo.h2"> Create Account </MudText>
<EditForm Model="@_userForRegistration" OnValidSubmit="Register" FormName="RegistrationForm">
<DataAnnotationsValidator />
<MudGrid>
<MudItem xs="12" sm="7">
<MudCard>
<MudCardContent>
<MudTextField Label="Name" HelperText="Max. 8 characters"
@bind-Value="_userForRegistration.Name" For="@(() => _userForRegistration.Email)" />
<MudTextField Label="Email" Class="mt-3"
@bind-Value="_userForRegistration.Email" For="@(() => _userForRegistration.Email)" />
<MudTextField Label="Password" HelperText="Choose a strong password" Class="mt-3"
@bind-Value="_userForRegistration.Password" For="@(() => _userForRegistration.Password)" InputType="InputType.Password" />
<MudTextField Label="Password" HelperText="Repeat the password" Class="mt-3"
@bind-Value="_userForRegistration.ConfirmPassword" For="@(() => _userForRegistration.ConfirmPassword)" InputType="InputType.Password" />
<MudRadioGroup T="UserRoles" Label="Roles" @bind-Value="_userForRegistration.Roles">
@foreach (UserRoles item in Enum.GetValues(typeof(UserRoles)))
{
if (item != UserRoles.Administrator)
{
<MudRadio Value="@item">@item.ToString()</MudRadio>
}
}
</MudRadioGroup>
<MudStack Row="true">
<MudTextField Label="Class"
HelperText="Enter a class number between 1 and 14."
Class="mt-3"
@bind-Value="_userForRegistration.Class"
For="@(() => _userForRegistration.Class)"
InputType="InputType.Number"
Required="true"
RequiredError="Class is required." />
<MudTextField Label="Grade"
HelperText="Enter a grade number between 1 and 6."
Class="mt-3"
@bind-Value="_userForRegistration.Grade"
For="@(() => _userForRegistration.Grade)"
InputType="InputType.Number"
Required="true"
RequiredError="Grade is required." />
</MudStack>
<MudTextField Label="Phone Number"
HelperText="Enter your phone number (optional, 7-20 digits)."
Class="mt-3"
@bind-Value="_userForRegistration.PhoneNumber"
For="@(() => _userForRegistration.PhoneNumber)"
InputType="InputType.Telephone" /> <MudTextField Label="Home Address"
HelperText="Enter your home address (optional, max 200 characters)."
Class="mt-3"
@bind-Value="_userForRegistration.HomeAddress"
For="@(() => _userForRegistration.HomeAddress)"
Lines="3" />
</MudCardContent>
<MudCardActions>
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" Color="Color.Primary" Class="ml-auto">Register</MudButton>
</MudCardActions>
</MudCard>
</MudItem>
<MudItem xs="12" sm="5">
<MudPaper Class="pa-4 mud-height-full">
<MudText Typo="Typo.subtitle2">Validation Summary</MudText>
@if (success)
{
<MudText Color="Color.Success">Success</MudText>
}
else
{
<MudText Color="@Color.Error">
<ValidationSummary />
</MudText>
}
</MudPaper>
</MudItem>
<MudItem xs="12">
<MudText Typo="Typo.body2" Align="Align.Center">
Fill out the form correctly to see the success message.
</MudText>
</MudItem>
</MudGrid>
</EditForm>

View File

@@ -0,0 +1,62 @@
using TechHelper.Client.HttpRepository;
using Entities.DTO;
using Microsoft.AspNetCore.Components;
using MudBlazor;
using System.Text.RegularExpressions;
using TechHelper.Features;
using Entities.Contracts;
namespace TechHelper.Client.Pages.Author
{
public partial class Registration
{
private UserForRegistrationDto _userForRegistration = new UserForRegistrationDto();
[Inject]
public IAuthenticationClientService AuthenticationService { get; set; }
[Inject]
public NavigationManager NavigationManager { get; set; }
public bool ShowRegistrationErrors { get; set; }
public string[] Errors { get; set; }
private bool success;
public async Task Register()
{
ShowRegistrationErrors = false;
var result = await AuthenticationService.RegisterUserAsync(_userForRegistration);
if (!result.IsSuccessfulRegistration)
{
int index = 0;
foreach (var error in result.Errors)
{
Errors[index] = error;
index++;
}
ShowRegistrationErrors = true;
Snackbar.Add(Errors.ToString());
}
else
{
NavigationManager.NavigateTo("/");
}
}
[Inject]
public IEmailSender emailSender { get; set; }
public async void SendEmail()
{
string eamilTo = "1928360026@qq.com";
string authCode = "123456";
await emailSender.SendEmailAuthcodeAsync(eamilTo, authCode);
}
}
}

View File

@@ -0,0 +1,49 @@
@page "/resetpassword"
<MudText Typo="Typo.h2"> Reset Password Account </MudText>
<EditForm Model="@_resetPassDto" OnValidSubmit="Submit" FormName="ResetPasswordForm">
<DataAnnotationsValidator />
<MudGrid>
<MudItem xs="12" sm="7">
<MudCard>
<MudCardContent>
<MudTextField Label="Password" HelperText="Choose a strong password" Class="mt-3"
@bind-Value="_resetPassDto.Password" For="@(() => _resetPassDto.Password)" InputType="InputType.Password" />
<MudTextField Label="Confirm Password" HelperText="Repet Password" Class="mt-3"
@bind-Value="_resetPassDto.ConfirmPassword" For="@(() => _resetPassDto.ConfirmPassword)" InputType="InputType.Password" />
</MudCardContent>
<MudCardActions>
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" Color="Color.Primary" Class="ml-auto">Register</MudButton>
</MudCardActions>
<div class="nav-item px-3">
<NavLink class="nav-link" href="forgotpassword">
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span>Forgot Password
</NavLink>
</div>
</MudCard>
</MudItem>
<MudItem xs="12" sm="5">
<MudPaper Class="pa-4 mud-height-full">
<MudText Typo="Typo.subtitle2">Validation Summary</MudText>
@if (_showSuccess)
{
<MudText Color="Color.Success">Success</MudText>
}
else if (_showError)
{
<MudText Color="@Color.Error">
<ValidationSummary />
</MudText>
}
</MudPaper>
</MudItem>
<MudItem xs="12">
<MudText Typo="Typo.body2" Align="Align.Center">
Fill out the form correctly to see the success message.
</MudText>
</MudItem>
</MudGrid>
</EditForm>

View File

@@ -0,0 +1,55 @@
using Entities.DTO;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.WebUtilities;
using TechHelper.Client.HttpRepository;
namespace TechHelper.Client.Pages.Author
{
public partial class ResetPassword : ComponentBase
{
private readonly ResetPasswordDto _resetPassDto = new ResetPasswordDto();
private bool _showSuccess;
private bool _showError;
private IEnumerable<string> _errors;
[Inject]
public IAuthenticationClientService AuthenticationClientService { get; set; }
[Inject]
public NavigationManager NavigationManager { get; set; }
protected override void OnInitialized()
{
var uri = NavigationManager.ToAbsoluteUri(NavigationManager.Uri);
var queryStrings = QueryHelpers.ParseQuery(uri.Query);
if (queryStrings.TryGetValue("email", out var email) &&
queryStrings.TryGetValue("token", out var token))
{
_resetPassDto.Email = email;
_resetPassDto.Token = token;
}
else
{
NavigationManager.NavigateTo("/");
}
}
private async Task Submit()
{
_showSuccess = _showError = false;
var result = await AuthenticationClientService.ResetPasswordAsync(_resetPassDto);
if(result.IsResetPasswordSuccessful)
_showSuccess = true;
else
{
_errors = result.Errors;
_showError = true;
}
NavigationManager.NavigateTo("/");
}
}
}

View File

@@ -0,0 +1,11 @@
@page "/rodetail"
<h3>RoleDetailInfo</h3>
<AuthorizeView>
<MudText> @context.User.Identity.Name </MudText>
</AuthorizeView>
@code {
}

View File

@@ -0,0 +1,47 @@
@page "/logout"
@inject IAuthenticationClientService AuthenticationClientService
@inject NavigationManager NavigationManager
<MudText>HELLO WORLD </MudText>
@code {
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// 作用:这个方法在组件渲染到 UI 后被调用。
// 意义:这是执行 JS 互操作的安全时机,特别是在启用了预渲染的情况下,
// 此时客户端的 JS 运行时已经可用(在 Blazor Server 中通过 SignalR在 Blazor WASM 中是 WASM 环境本身)。
// firstRender 参数:
// 作用:指示本次调用是否是组件首次在客户端渲染完成。
// 意义:注销逻辑只需要执行一次。使用 firstRender = true 可以避免在组件后续状态变化触发重新渲染时重复执行。
if (firstRender)
{
Console.WriteLine("Signout: OnAfterRenderAsync - First Render. Executing Logout..."); // 可选日志
try
{
// === 在这里安全地调用依赖 JS Interop 的注销方法 ===
// AuthenticationClientService.Logout() 方法内部会调用 _localStorageService.RemoveItemAsync(),
// 现在是调用它的安全时机。
// 注销完成后,执行导航重定向
NavigationManager.NavigateTo("/");
}
catch (Exception ex)
{
// === 处理 Logout 中可能发生的异常 ===
// 例如,如果 Local Storage 操作失败,或者 Logout 方法内部有其他错误
Console.WriteLine($"Error during logout in Signout component: {ex.Message}");
// 你可能需要在这里显示错误信息给用户,或者决定是否依然重定向
// 即使注销失败,通常也希望将用户导航到某个页面(如首页或错误页)
// 例如:
NavigationManager.NavigateTo("/"); // 即使失败也重定向到首页
// 或者 NavigationManager.NavigateTo("/error"); // 重定向到错误页
}
Console.WriteLine("Signout: OnAfterRenderAsync - First Render. Logout execution finished."); // 可选日志
}
}
}

View File

@@ -0,0 +1,39 @@
@page "/twostepverification"
<EditForm Model="@_twoFactorVerificationDto" OnValidSubmit="Submit" FormName="ForgotForm">
<DataAnnotationsValidator />
<MudGrid>
<MudItem xs="12" sm="7">
<MudCard>
<MudCardContent>
<MudTextField Label="Email" Class="mt-3"
@bind-Value="_twoFactorVerificationDto.TwoFactorToken" For="@(() => _twoFactorVerificationDto.TwoFactorToken)" />
</MudCardContent>
<MudCardActions>
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" Color="Color.Primary" Class="ml-auto">Register</MudButton>
</MudCardActions>
</MudCard>
</MudItem>
<MudItem xs="12" sm="5">
<MudPaper Class="pa-4 mud-height-full">
<MudText Typo="Typo.subtitle2">Validation Summary</MudText>
@if (_showSuccess)
{
<MudText Color="Color.Success">Success</MudText>
}
else if (_showError)
{
<MudText Color="@Color.Error">
<ValidationSummary />
</MudText>
}
</MudPaper>
</MudItem>
<MudItem xs="12">
<MudText Typo="Typo.body2" Align="Align.Center">
Fill out the form correctly to see the success message.
</MudText>
</MudItem>
</MudGrid>
</EditForm>

View File

@@ -0,0 +1,60 @@
using Entities.DTO;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.WebUtilities;
using TechHelper.Client.HttpRepository;
namespace TechHelper.Client.Pages.Author
{
public partial class TwoStepVerification : ComponentBase
{
private TwoFactorVerificationDto _twoFactorVerificationDto = new TwoFactorVerificationDto();
private bool _showSuccess;
private string? _error;
private bool _showError;
[Inject]
public IAuthenticationClientService AuthenticationClientService { get; set; }
[Inject]
public NavigationManager NavigationManager { get; set; }
[SupplyParameterFromQuery]
[Parameter]
public string? Email { get; set; }
[SupplyParameterFromQuery]
[Parameter]
public string? Provider { get; set; }
protected override void OnInitialized()
{
if(string.IsNullOrEmpty(Email) || string.IsNullOrEmpty(Provider))
{
NavigationManager.NavigateTo("/");
}
else
{
_twoFactorVerificationDto.Email = Email;
_twoFactorVerificationDto.Provider = Provider;
}
}
private async Task Submit()
{
_showError = false;
var result = await AuthenticationClientService.LoginVerfication(_twoFactorVerificationDto);
if(result.IsAuthSuccessful)
NavigationManager.NavigateTo("/");
else
{
_error = result.ErrorMessage;
_showError = true;
}
}
}
}