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()
{
// 首先检查 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, _, _) = await _apiService.GetExportCountAsync(new WorkRecordExportQuery
{
PageNum = 1,
PageSize = 1
});
if (success)
{
CurrentUsername = _settings.Username;
StartTokenCheckTimer();
_logService?.Info($"自动登录成功,用户: {CurrentUsername}");
return true;
}
_logService?.Warn("Token 验证失败,清除登录信息");
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
{
var (success, _, _) = await _apiService.GetExportCountAsync(new WorkRecordExportQuery
{
PageNum = 1,
PageSize = 1
});
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;
}
}
}