using HandyControl.Data; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Threading; using YY.Admin.Core; using YY.Admin.Core.Const; using YY.Admin.Core.EventBus; using YY.Admin.Core.Session; using YY.Admin.Services.Service.Auth; using YY.Admin.Views; namespace YY.Admin.ViewModels { public class BaseViewModel : BindableBase, IDestructible { protected bool _isLoading; private string _title = string.Empty; // 添加Token检查定时器 private static DispatcherTimer? _tokenCheckTimer; /// ///加载 /// public bool IsLoading { get => _isLoading; set { if (SetProperty(ref _isLoading, value)) { // 触发一个虚拟方法,让派生类可以响应 OnIsLoadingChanged(); } } } public bool IsNotLoading => !IsLoading; /// ///标题 /// public string Title { get => _title; set => SetProperty(ref _title, value); } private readonly IDialogService _dialogService; protected readonly IRegionManager _regionManager; /// /// 日志对象 /// protected ILoggerService _logger; /// /// 依赖注入容器 /// protected IContainerExtension _container { get; } /// /// 事件汇总器,用于发布或订阅事件 /// protected IEventAggregator _eventAggregator; /// /// 当前已登录用户信息 /// protected static UserContext? _userContext { get; set; } private SkinType _skinType; public SkinType SkinType { get => _skinType; set => SetProperty(ref _skinType, value); } private SubscriptionToken? _themeChangedEventToken; protected BaseViewModel(IContainerExtension container, IRegionManager regionManager) { _container = container; _logger = container.Resolve(); _eventAggregator = container.Resolve(); this._dialogService = container.Resolve(); this._regionManager = regionManager; _themeChangedEventToken = _eventAggregator.GetEvent().Subscribe(skinType => SkinType = skinType); } #region 用户操作 // 启动定时器的方法 public static void StartTokenCheckTimer() { if (_tokenCheckTimer == null) { _tokenCheckTimer = new DispatcherTimer { Interval = TimeSpan.FromMinutes(1) }; _tokenCheckTimer.Tick += CheckTokenExpiration; // 捕获全局用户输入事件 EventManager.RegisterClassHandler(typeof(Window), UIElement.PreviewMouseDownEvent, new MouseButtonEventHandler(OnUserActivity)); EventManager.RegisterClassHandler(typeof(Window), UIElement.PreviewKeyDownEvent, new KeyEventHandler(OnUserActivity)); } if (!_tokenCheckTimer.IsEnabled) { _tokenCheckTimer.Start(); } } // 停止定时器的方法 public static void StopTokenCheckTimer() { if (_tokenCheckTimer != null && _tokenCheckTimer.IsEnabled) { _tokenCheckTimer.Stop(); } } private static void OnUserActivity(object sender, EventArgs e) { var authService = ContainerLocator.Current.Resolve(); authService.RefreshToken(UserContext?.Token?.AccessToken); } /// ///定时器检查方法 /// /// /// private static void CheckTokenExpiration(object? sender, EventArgs e) { // 确保在主线程执行 Application.Current.Dispatcher.Invoke(() => { if (UserContext == null || UserContext.Token == null) { // 如果没有用户信息,停止定时器 StopTokenCheckTimer(); return; } var authService = ContainerLocator.Current.Resolve(); if (!authService.ValidateToken(UserContext.Token.AccessToken)) { // 停止定时器防止重复触发 StopTokenCheckTimer(); // 显示过期提示 Application.Current.Dispatcher.Invoke(() => { var currentWindow = Application.Current.MainWindow; if (currentWindow != null) { var viewModel = currentWindow.DataContext as BaseViewModel; viewModel?.ForceLogout("您的登录已过期,请重新登录"); } }); } }); } /// /// 强制退出方法 /// /// public async void ForceLogout(string message) { // 先显示对话框 await ShowAlertAsync(message); // 发布登出事件 _eventAggregator.GetEvent().Publish(AppSession.CurrentUser!); Logout(); } /// /// 登出 /// public void Logout() { // 停止定时器 StopTokenCheckTimer(); // 清除用户上下文 ClearUserContext(); // 再执行退出操作 var authService = _container.Resolve(); authService.LogoutAsync(); // 当前窗口 var mainWindow = Application.Current.MainWindow; // 跳转到登录页 var loginWindow = _container.Resolve(); Application.Current.MainWindow = loginWindow; loginWindow.Show(); mainWindow.Close(); // 移除所有区域 RemoveAllRegion(); } public static UserContext? UserContext { get => _userContext; private set { if (_userContext != value) { _userContext = value; // 通知静态属性变化(需要额外实现) StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(nameof(UserContext))); } } } // 静态属性变更通知事件 public static event EventHandler? StaticPropertyChanged; /// /// 设置用户上下文 /// /// /// public static void SetUserContext(SysUser user, UserToken token) { UserContext = new UserContext { UserId = user.Id, TenantId = user.TenantId!.Value, Account = user.Account, AccountType = user.AccountType, RealName = user.RealName, IsSuperAdmin = user.AccountType == AccountTypeEnum.SuperAdmin, OrgId = user.OrgId, Token = token }; } /// /// 清除用户上下文 /// public static void ClearUserContext() { UserContext = null; } #endregion #region 导航 /// /// 导航到指定Page /// /// 区域名称 /// 目标Page名称 /// 导航回调函数 protected void RequestNavigate(string regionName, string target, Action navigationCallback = null) { IRegion region = _regionManager.Regions[regionName]; if (region == null) return; region.RemoveAll(); if (navigationCallback != null) region.RequestNavigate(target, navigationCallback); else region.RequestNavigate(target); } protected void SetRegionManager(DependencyObject target) { RegionManager.SetRegionManager(target, _regionManager); } /// /// 安全导航到指定视图 /// protected void SafeNavigate(string regionName, string targetView, NavigationParameters parameters = null) { ExecuteWithExceptionHandling(() => { // 导航页面 _regionManager.RequestNavigate(regionName, targetView, parameters); }); } protected void ExecuteWithExceptionHandling(Action action) { try { action(); } catch (Exception ex) { HandleException(ex); } } private void HandleException(Exception ex) { LogError("操作发生异常", ex); // ShowErrorDialog($"操作异常: {ex.Message}"); } #endregion #region 弹出框 /// /// 弹框提示 /// /// 消息内容 /// 回调函数 protected void Alert(string message, Action? callback = null) { _dialogService.ShowDialog("AlertDialog", new DialogParameters($"message={message}"), callback); } protected Task ShowAlertAsync(string message) { var tcs = new TaskCompletionSource(); Alert(message,result => tcs.SetResult(true)); return tcs.Task; } /// /// 弹出消息提示框,1秒钟自动关闭 /// /// 消息内容 /// 消息类型 /// 回调函数 protected void AlertPopup(string message, MessageTypeEnum messageType = MessageTypeEnum.Success, Action callback = null) { switch (messageType) { case MessageTypeEnum.Success: _dialogService.ShowDialog("SuccessDialog", new DialogParameters($"message={message}"), callback); break; case MessageTypeEnum.Error: _dialogService.ShowDialog("ErrorDialog", new DialogParameters($"message={message}"), callback); break; case MessageTypeEnum.Warning: _dialogService.ShowDialog("WarningDialog", new DialogParameters($"message={message}"), callback); break; default: _dialogService.ShowDialog("SuccessDialog", new DialogParameters($"message={message}"), callback); break; } } /// /// 确认框提示 /// /// 确认框消息 /// 回调函数 protected void Confirm(string message, Action? callback = null) { _dialogService.ShowDialog("ConfirmDialog", new DialogParameters($"message={message}"), callback); } /// /// 异步确认框 /// /// 确认消息 /// 用户是否确认 protected Task ConfirmAsync(string message) { var tcs = new TaskCompletionSource(); Confirm(message, result => { // 从 IDialogResult 中提取用户选择 var userConfirmed = result.Result == ButtonResult.Yes; tcs.SetResult(userConfirmed); }); return tcs.Task; } #endregion #region 日志功能封装 protected void LogInfo(string message, [CallerMemberName] string caller = "") => _logger.Information($"[{GetType().Name}.{caller}] {message}"); protected void LogWarning(string message, [CallerMemberName] string caller = "") => _logger.Warning($"[{GetType().Name}.{caller}] {message}"); protected void LogError(string message, Exception ex = null, [CallerMemberName] string caller = "") => _logger.Error($"[{GetType().Name}.{caller}] {message}", ex); #endregion /// /// 异常处理封装 /// /// /// /// protected async Task ExecuteAsync(Func asyncAction, Action? onFinally = null) { try { IsLoading = true; await asyncAction(); } catch (Exception ex) { HandleException(ex); } finally { IsLoading = false; onFinally?.Invoke(); } } /// /// 窗口管理 /// /// protected void SwitchMainWindow() where T : Window { ExecuteWithExceptionHandling(() => { var currentWindow = Application.Current.MainWindow; var newWindow = _container.Resolve(); Application.Current.MainWindow?.Hide(); Application.Current.MainWindow = newWindow; newWindow.Show(); currentWindow?.Close(); }); } /// /// 资源管理 /// /// /// /// /// protected T GetResource(string resourceKey) { if (Application.Current.TryFindResource(resourceKey) is T resource) { return resource; } throw new ResourceNotFoundException($"资源未找到: {resourceKey}"); } /// /// 移除区域,包括清空区域内的内容,导航日志 /// /// 区域名称 protected void RemoveRegion(string regionName) { if (string.IsNullOrEmpty(regionName)) { return; } if (!_regionManager.Regions.ContainsRegionWithName(regionName)) { return; } var region = _regionManager.Regions[regionName]; RemoveRegion(region); } /// /// 移除区域,包括清空区域内的内容,导航日志 /// /// protected void RemoveRegion(IRegion region) { if (region == null) { return; } // 清空区域内容 region.RemoveAll(); // 清空导航历史 region.NavigationService?.Journal?.Clear(); // 从区域管理器中移除区域 _regionManager.Regions.Remove(region.Name); _logger.Debug($"移除区域{region.Name}"); } /// /// 移除所有区域 /// protected void RemoveAllRegion() { foreach (var region in _regionManager.Regions.ToList()) { RemoveRegion(region); } _logger.Debug($"移除所有区域"); } /// /// 移除区域视图 /// /// 区域名称 /// 视图名称 protected void RemoveView(string regionName, string? viewName) { if (string.IsNullOrEmpty(regionName) || string.IsNullOrEmpty(viewName)) { return; } if (!_regionManager.Regions.ContainsRegionWithName(regionName)) { return; } var region = _regionManager.Regions[regionName]; // 查找并移除指定的视图 var viewToRemove = region.Views.FirstOrDefault(v => { // 根据视图名称或类型来匹配 var viewType = v.GetType(); return viewType.Name == viewName || viewType.Name == viewName + "View"; }); if (viewToRemove != null) { region.Remove(viewToRemove); _logger.Debug($"从区域{regionName}移除视图{viewName}"); } } /// /// 移除区域ContentRegion视图 /// /// protected void RemoveContentRegionView(string? viewName) { RemoveView(CommonConst.ContentRegion, viewName); } /// /// 移除区域所有视图 /// /// 区域名称 protected void RemoveAllView(string regionName) { if (string.IsNullOrEmpty(regionName)) { return; } if (!_regionManager.Regions.ContainsRegionWithName(regionName)) { return; } var region = _regionManager.Regions[regionName]; region.RemoveAll(); _logger.Debug($"移除区域{regionName}所有视图"); } /// /// 当 IsLoading 变化时的回调方法 /// protected virtual void OnIsLoadingChanged() { RaisePropertyChanged(nameof(IsNotLoading)); } /// /// 清理资源 /// protected virtual void CleanUp() { } /// /// 清空资源 /// 执行时机:从Region移除View 或 导航到另一个View时 /// public void Destroy() { if (_themeChangedEventToken != null) { _eventAggregator.GetEvent().Unsubscribe(_themeChangedEventToken); _themeChangedEventToken = null; } // 清理派生类的资源 CleanUp(); } } // 自定义异常类型 public class ResourceNotFoundException : Exception { public ResourceNotFoundException(string message) : base(message) { } } }