using WorkCameraExport.Models; using WorkCameraExport.Services.Interfaces; namespace WorkCameraExport.Services { /// /// 登录状态管理器 - 负责管理登录状态、自动登录、登录失效检测 /// public class LoginStateManager : IDisposable { private readonly ApiService _apiService; private readonly IConfigService _configService; private readonly ILogService? _logService; private readonly AppSettings _settings; private System.Threading.Timer? _tokenCheckTimer; private bool _disposed; // Token 检查间隔(5分钟) private const int TokenCheckIntervalMs = 5 * 60 * 1000; // Token 即将过期阈值(10分钟) private const int TokenExpiryThresholdMinutes = 10; /// /// 登录失效事件 /// public event EventHandler? LoginExpired; /// /// Token 即将过期事件 /// public event EventHandler? TokenExpiringSoon; /// /// 当前登录用户名 /// public string? CurrentUsername { get; private set; } /// /// 是否已登录 /// public bool IsLoggedIn => _apiService.IsLoggedIn; public LoginStateManager( ApiService apiService, IConfigService configService, ILogService? logService = null) { _apiService = apiService; _configService = configService; _logService = logService; _settings = AppSettings.Load(); } /// /// 尝试自动登录 /// /// 是否自动登录成功 public async Task TryAutoLoginAsync() { // 每次尝试自动登录时重新加载设置,确保获取最新的保存信息 var settings = AppSettings.Load(); _logService?.Info($"[自动登录] 检查设置: RememberMe={settings.RememberMe}, ServerUrl={settings.ServerUrl}, SavedToken长度={settings.SavedToken?.Length ?? 0}"); // 首先检查 AppSettings 中的保存信息 if (!settings.RememberMe || string.IsNullOrEmpty(settings.ServerUrl) || string.IsNullOrEmpty(settings.SavedToken)) { _logService?.Info("未找到保存的登录信息,跳过自动登录"); return false; } // 检查 Token 是否已过期 if (settings.TokenExpireTime.HasValue && settings.TokenExpireTime.Value <= DateTime.Now) { _logService?.Info("保存的 Token 已过期,清除登录信息"); ClearLoginState(); return false; } _logService?.Info("尝试自动登录..."); try { _apiService.SetBaseUrl(settings.ServerUrl); _apiService.SetToken(settings.SavedToken); // 验证 Token 是否有效(通过获取当前用户信息) var (success, message, userInfo) = await _apiService.GetCurrentUserAsync(); if (success && userInfo != null) { CurrentUsername = userInfo.UserName ?? settings.Username; StartTokenCheckTimer(); _logService?.Info($"自动登录成功,用户: {CurrentUsername}"); return true; } _logService?.Warn($"Token 验证失败: {message},清除登录信息"); ClearLoginState(); return false; } catch (Exception ex) { _logService?.Error($"自动登录异常: {ex.Message}", ex); ClearLoginState(); return false; } } /// /// 登录成功后调用,保存登录状态 /// public void OnLoginSuccess(string serverUrl, string username, string token, bool rememberMe) { CurrentUsername = username; _settings.ServerUrl = serverUrl; _settings.Username = username; _settings.RememberMe = rememberMe; if (rememberMe) { _settings.SavedToken = token; _settings.TokenExpireTime = DateTime.Now.AddDays(7); _configService.SaveCredentials(serverUrl, token, username); } else { _settings.SavedToken = ""; _settings.TokenExpireTime = null; _configService.ClearCredentials(); } _settings.Save(); StartTokenCheckTimer(); _logService?.Info($"登录成功,用户: {username},记住登录: {rememberMe}"); } /// /// 自动登录成功后调用,仅启动定时器,不重新保存凭证 /// public void OnAutoLoginSuccess(string username) { CurrentUsername = username; StartTokenCheckTimer(); _logService?.Info($"自动登录成功,用户: {username}"); } /// /// 退出登录 /// public void Logout() { _logService?.Info($"用户 {CurrentUsername} 退出登录"); StopTokenCheckTimer(); _apiService.Logout(); ClearLoginState(); CurrentUsername = null; } /// /// 清除登录状态 /// public void ClearLoginState() { _settings.ClearLoginInfo(); _configService.ClearCredentials(); } /// /// 检查登录状态是否有效 /// public async Task CheckLoginStateAsync() { if (!_apiService.IsLoggedIn) { return false; } try { // 通过获取当前用户信息验证 Token 有效性 var (success, _, _) = await _apiService.GetCurrentUserAsync(); if (!success) { OnLoginExpired("登录已失效,请重新登录"); return false; } return true; } catch { return false; } } /// /// 启动 Token 检查定时器 /// private void StartTokenCheckTimer() { StopTokenCheckTimer(); _tokenCheckTimer = new System.Threading.Timer( CheckTokenExpiry, null, TokenCheckIntervalMs, TokenCheckIntervalMs); } /// /// 停止 Token 检查定时器 /// private void StopTokenCheckTimer() { _tokenCheckTimer?.Dispose(); _tokenCheckTimer = null; } /// /// 检查 Token 是否即将过期 /// private void CheckTokenExpiry(object? state) { if (_settings.TokenExpireTime.HasValue) { var timeUntilExpiry = _settings.TokenExpireTime.Value - DateTime.Now; if (timeUntilExpiry.TotalMinutes <= 0) { // Token 已过期 OnLoginExpired("登录已过期,请重新登录"); } else if (timeUntilExpiry.TotalMinutes <= TokenExpiryThresholdMinutes) { // Token 即将过期,尝试刷新 _logService?.Info("Token 即将过期,触发刷新事件"); TokenExpiringSoon?.Invoke(this, EventArgs.Empty); } } } /// /// 触发登录失效事件 /// private void OnLoginExpired(string reason) { _logService?.Warn($"登录失效: {reason}"); StopTokenCheckTimer(); LoginExpired?.Invoke(this, new LoginExpiredEventArgs(reason)); } #region IDisposable public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { StopTokenCheckTimer(); } _disposed = true; } } #endregion } /// /// 登录失效事件参数 /// public class LoginExpiredEventArgs : EventArgs { public string Reason { get; } public LoginExpiredEventArgs(string reason) { Reason = reason; } } }