using System.Windows;
using System.Windows.Media;
using System.Net.Http;
using Microsoft.Extensions.Configuration;
using Prism.Dialogs;
using YY.Admin;
using YY.Admin.Core.Helper;
using YY.Admin.Core.Session;
using YY.Admin.FluentValidation;
using YY.Admin.Helper;
using YY.Admin.Services;
using YY.Admin.Services.Service.Auth;
using YY.Admin.Services.Service.Jeecg;
using YY.Admin.Views;
namespace YY.Admin.ViewModels
{
// ViewModels/LoginViewModel.cs
public class LoginWindowViewModel : BaseViewModel
{
private readonly ISysAuthService _authService;
private readonly IDialogService _dialogService;
private readonly IJeecgLoginLogReportService _loginLogReportService;
private readonly IConfiguration _configuration;
private readonly HttpClient _httpClient = new();
private readonly CancellationTokenSource _connectivityCts = new();
private const int ConnectivityCheckIntervalSeconds = 5;
public LoginInput LoginInput { get; set; }
private string _loginMessage = string.Empty;
public DelegateCommand LoginCommand { get; }
public DelegateCommand SyncJeecgUsersCommand { get; }
public DelegateCommand OpenServerSettingsCommand { get; }
public LoginInputValidator LoginInputValidator { get; private set; }
private bool _isSyncingJeecgUsers;
///
/// 正在从 Jeecg 同步用户到本地库
///
public bool IsSyncingJeecgUsers
{
get => _isSyncingJeecgUsers;
set
{
if (SetProperty(ref _isSyncingJeecgUsers, value))
{
SyncJeecgUsersCommand.RaiseCanExecuteChanged();
LoginCommand.RaiseCanExecuteChanged();
RaisePropertyChanged(nameof(SyncJeecgUsersButtonText));
RaisePropertyChanged(nameof(CanInteractWithLogin));
}
}
}
public string SyncJeecgUsersButtonText => IsSyncingJeecgUsers ? "同步中..." : "同步 Jeecg 用户";
/// 登录与同步互斥,用于禁用登录按钮
public bool CanInteractWithLogin => !IsLoading && !IsSyncingJeecgUsers;
private bool _isBackendConnected;
///
/// 后端连接状态:true=连接中,false=已断开
///
public bool IsBackendConnected
{
get => _isBackendConnected;
set
{
if (SetProperty(ref _isBackendConnected, value))
{
RaisePropertyChanged(nameof(BackendConnectionStatusText));
RaisePropertyChanged(nameof(BackendConnectionStatusBrush));
}
}
}
public string BackendConnectionStatusText => IsBackendConnected ? "后端连接中" : "后端已断开";
public Brush BackendConnectionStatusBrush => IsBackendConnected ? Brushes.LimeGreen : Brushes.Red;
public LoginWindowViewModel(
ISysAuthService authService,
IDialogService dialogService,
IJeecgLoginLogReportService loginLogReportService,
IContainerExtension _container,
IRegionManager regionManager
) : base(_container, regionManager)
{
_authService = authService;
_dialogService = dialogService;
_loginLogReportService = loginLogReportService;
_configuration = _container.Resolve();
_loginLogReportService.StartBackgroundSync();
Title = "系统登录";
LoginInput = new LoginInput()
{
Username = "admin",
Password = "123456"
};
LoginInputValidator = new LoginInputValidator();
LoginCommand = new DelegateCommand(async () => await LoginAsync(), CanLogin)
.ObservesProperty(() => IsLoading)
.ObservesProperty(() => IsSyncingJeecgUsers);
SyncJeecgUsersCommand = new DelegateCommand(async () => await SyncJeecgUsersAsync(), CanSyncJeecgUsers)
.ObservesProperty(() => IsLoading)
.ObservesProperty(() => IsSyncingJeecgUsers);
OpenServerSettingsCommand = new DelegateCommand(OpenServerSettings);
_ = StartBackendConnectivityLoopAsync(_connectivityCts.Token);
}
public string LoginMessage
{
get => _loginMessage;
set => SetProperty(ref _loginMessage, value);
}
public string LoginButtonText => IsLoading ? "登录中..." : "登录";
protected override void OnIsLoadingChanged()
{
base.OnIsLoadingChanged();
RaisePropertyChanged(nameof(LoginButtonText));
RaisePropertyChanged(nameof(CanInteractWithLogin));
LoginCommand.RaiseCanExecuteChanged();
SyncJeecgUsersCommand.RaiseCanExecuteChanged();
}
private bool CanLogin()
{
return !IsLoading && !IsSyncingJeecgUsers;
}
private bool CanSyncJeecgUsers()
{
return !IsLoading && !IsSyncingJeecgUsers;
}
private async Task SyncJeecgUsersAsync()
{
LoginMessage = string.Empty;
IsSyncingJeecgUsers = true;
try
{
await UIHelper.WaitForRenderAsync();
var (success, message) = await _authService.SyncJeecgUsersToLocalFromLoginScreenAsync();
LoginMessage = message;
if (success)
{
_logger?.Information("登录页一键同步 Jeecg 用户成功");
}
else
{
_logger?.Warning($"登录页一键同步 Jeecg 用户:{message}");
}
}
catch (Exception ex)
{
LoginMessage = $"同步出错:{ex.Message}";
}
finally
{
IsSyncingJeecgUsers = false;
}
}
private async Task LoginAsync()
{
IsLoading = true;
//LoginMessage = string.Empty;
try
{
// 让出线程,让UI先渲染
await UIHelper.WaitForRenderAsync();
var response = await _authService.LoginAsync(LoginInput);
if (response.Success)
{
_ = _loginLogReportService.ReportLoginAsync(LoginInput.Username, true, "登录成功");
_connectivityCts.Cancel();
//设置会话
AppSession.CurrentUser = response.User;
// 设置用户上下文
SetUserContext(response.User!, response.Token);
// 启动定时器
StartTokenCheckTimer();
// 登录成功,打开主窗口
var loginWindow = Application.Current.MainWindow;
var mainWindow = _container.Resolve();
Application.Current.MainWindow = mainWindow;
//把窗口和RegionManager 绑定一下即可
SetRegionManager(mainWindow);
mainWindow.Show();
loginWindow.Close();
// 不等待异步更新用户登录信息,不阻塞主窗口打开
_ = _authService.UpdateUserLoginInfoAsync(response.User!);
}
else
{
LoginMessage = response.Message;
_ = _loginLogReportService.ReportLoginAsync(LoginInput.Username, false, response.Message);
}
}
catch (Exception ex)
{
LoginMessage = $"登录出错:{ex.Message}";
_ = _loginLogReportService.ReportLoginAsync(LoginInput.Username, false, ex.Message);
}
finally
{
IsLoading = false;
}
}
private async Task StartBackendConnectivityLoopAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
bool connected = false;
var settings = ServerSettingsStore.Load();
if (settings.DisconnectConnection)
{
try
{
await Application.Current.Dispatcher.InvokeAsync(() =>
{
IsBackendConnected = false;
});
}
catch
{
// 忽略窗口关闭后的调度异常
}
try
{
await Task.Delay(TimeSpan.FromSeconds(ConnectivityCheckIntervalSeconds), cancellationToken);
}
catch (OperationCanceledException)
{
break;
}
continue;
}
try
{
// 每轮都重新读取配置,保存服务器设置后可即时生效
var baseUrl = _configuration.GetValue("JeecgIntegration:BaseUrl")?.TrimEnd('/');
var userListPath = _configuration.GetValue("JeecgIntegration:UserListPath") ?? "/sys/user/scada/queryUser";
var probeUrl = string.IsNullOrWhiteSpace(baseUrl)
? string.Empty
: $"{baseUrl}{userListPath}?pageNo=1&pageSize=1&includeDetail=false";
if (!string.IsNullOrWhiteSpace(probeUrl))
{
using var req = new HttpRequestMessage(HttpMethod.Get, probeUrl);
using var resp = await _httpClient.SendAsync(req, cancellationToken);
connected = resp.IsSuccessStatusCode;
}
}
catch
{
connected = false;
}
try
{
await Application.Current.Dispatcher.InvokeAsync(() =>
{
IsBackendConnected = connected;
});
}
catch
{
// 忽略窗口关闭后的调度异常
}
try
{
await Task.Delay(TimeSpan.FromSeconds(ConnectivityCheckIntervalSeconds), cancellationToken);
}
catch (OperationCanceledException)
{
break;
}
}
}
private void OpenServerSettings()
{
var parameters = new DialogParameters
{
{ KnownDialogParameters.WindowName, DialogWindowNames.ChromeDialogWindow },
};
_dialogService.ShowDialog("ServerSettingsDialog", parameters, r =>
{
if (r.Result == ButtonResult.OK)
{
var settings = ServerSettingsStore.Load();
if (settings.DisconnectConnection)
{
IsBackendConnected = false;
}
LoginMessage = "服务器配置已保存";
}
});
}
}
}