@page "/account/login" @using System.Text.Json @layout EmptyLayout @inject ILogger Logger @inject IJSRuntime JS 登录 @if (!dataLoaded) { } else {
忘记密码 马上注册 设置开发帐号
Copyright © 2025-@DateTime.Now.Year Atomlust.com All rights reserved. runing as @handler
} @code { string handler = "Server"; [Parameter] [SupplyParameterFromQuery(Name = "ReturnUrl")] public string? ReturnUrl { get; set; } [SupplyParameterFromForm] public LoginModel login { get; set; } = new(); private Form form = null!; bool dataLoaded = false; string message { get; set; } = string.Empty; private bool _isLoading = false; protected override void OnInitialized() { if (OperatingSystem.IsBrowser()) { handler = "Wasm"; } else { handler = "Server"; } } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { var authState = await AuthStateProvider.GetAuthenticationStateAsync(); if (authState.User.Identity != null && authState.User.Identity.IsAuthenticated) { Navigation.NavigateTo(ReturnUrl ?? "/"); } } if (!dataLoaded) { dataLoaded = true; StateHasChanged(); } } private async Task LoginAsync() { if (!form.Validate()) return; _isLoading = true; StateHasChanged(); try { var api = "/api/sign/in"; if (!OperatingSystem.IsBrowser()) { // Server 模式:使用浏览器发起的 fetch(通过 JS)并携带 credentials: 'include' Logger.LogInformation("Server 模式,使用浏览器 fetch 登录"); var jsResult = await JS.InvokeAsync("__atomx_post_json", api, login); var success = jsResult.TryGetProperty("success", out var sprop) && sprop.GetBoolean(); if (success && jsResult.TryGetProperty("data", out var dprop) && dprop.ValueKind == JsonValueKind.Object) { var token = dprop.TryGetProperty("token", out var t) ? t.GetString() ?? string.Empty : string.Empty; var refresh = dprop.TryGetProperty("refreshToken", out var r) ? r.GetString() ?? string.Empty : string.Empty; // WASM 的 localStorage 在 Server Circuit 中无意义,兼容auto模式写入 localStorage。 try { await localStorage.SetItemAsync(StorageKeys.AccessToken, token); await localStorage.SetItemAsync(StorageKeys.RefreshToken, refresh); if (AuthStateProvider is PersistentAuthenticationStateProvider provider) { provider.UpdateAuthenticationState(token); } } catch { } // 浏览器已通过 fetch 收到 Set-Cookie;强制重载使 Circuit 使用新 Cookie。 Logger.LogInformation($"登录成功,server 跳转: {ReturnUrl}"); Navigation.NavigateTo(ReturnUrl ?? "/", forceLoad: true); } else { var msg = jsResult.TryGetProperty("message", out var m) ? m.GetString() ?? "登录失败" : "登录失败"; ModalService.Error(new ConfirmOptions() { Title = "提示", Content = msg }); } } else { // Wasm 模式:继续使用 HttpService(之前逻辑),保存 localStorage 并更新 AuthStateProvider var result = await HttpService.Post>(api, login); if (result.Success && result.Data != null) { var auth = result.Data; await localStorage.SetItemAsync(StorageKeys.AccessToken, auth.Token); await localStorage.SetItemAsync(StorageKeys.RefreshToken, auth.RefreshToken); if (AuthStateProvider is PersistentAuthenticationStateProvider provider) { provider.UpdateAuthenticationState(auth.Token); } Logger.LogInformation("登录成功,wasm 跳转: {ReturnUrl}", ReturnUrl); Navigation.NavigateTo(ReturnUrl ?? "/"); } else { ModalService.Error(new ConfirmOptions() { Title = "提示", Content = result.Message }); } } } catch (Exception ex) { Logger.LogError(ex, "登录失败"); ModalService.Error(new ConfirmOptions() { Title = "错误", Content = "登录异常,请稍后重试" }); } finally { _isLoading = false; StateHasChanged(); } } private async Task OnPasswordKeyDown(KeyboardEventArgs value) { if (value.Key == "Enter") { await LoginAsync(); } } void setAccount() { login.Account = "admin"; login.Password = "admin888"; } } @* 页面内 JS 辅助:用于在 Server 模式下从浏览器发起 POST 并携带凭证,使浏览器接收 Set-Cookie *@