using Avalonia; using Avalonia.Controls; using Avalonia.Media; using Avalonia.Styling; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Cowain.Base.Abstractions.Navigation; using Cowain.Base.Attributes; using Cowain.Base.Helpers; using Cowain.Base.IServices; using Cowain.Base.Models.Menu; using Cowain.Base.ViewModels; using Ke.Bee.Localization.Localizer.Abstractions; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Semi.Avalonia; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using MenuItem = Cowain.Base.Models.Menu.MenuItem; namespace Cowain.TestProject.ViewModels { public partial class LoginWindowViewModel : ViewModelBase { private class UserData { public string? UserName { get; set; } public string? Password { get; set; } public bool IsRemember { get; set; } } /// /// 登录成功 /// [ObservableProperty] private bool _loginSuccess; /// /// 是否记住用户名 /// [ObservableProperty] private bool _rememberUserName; /// /// 用户名 /// [ObservableProperty] [NotifyDataErrorInfo] [NotifyCanExecuteChangedFor(nameof(LoginCommand))] [MinLength(2, "Errors.MinLength")] private string? _userName; /// /// 密码 /// [ObservableProperty] [NotifyDataErrorInfo] [NotifyCanExecuteChangedFor(nameof(LoginCommand))] [MinLength(4, "Errors.MinLength")] private string? _password; /// /// 错误信息 /// [ObservableProperty] private string? _errorMessage; /// /// 当前页面视图模型 /// [ObservableProperty] private PageViewModelBase? _currentPage; /// /// 设置菜单集合 /// [ObservableProperty] private ObservableCollection? _settingMenus; private readonly ILocalizer _l; /// /// 视图导航器 /// private readonly IViewNavigator _viewNavigator; /// /// 菜单数据 /// private readonly List _menuItems; private ILogger _logger; private IAccountService _accountService; private IConfiguration _configuration; private string userFileName = "userdata.json"; public LoginWindowViewModel(MenuConfigurationContext menuContext, ILocalizer localizer, ILogger logger, IViewNavigator viewNavigator, IAccountService accountService, IConfiguration configuration) { _l = localizer; _logger = logger; string pdtName = GetProductName(); userFileName= $"{pdtName}_userdata.json"; _menuItems = menuContext.Menus; _viewNavigator = viewNavigator; _accountService = accountService; _configuration = configuration; LoadSettingMenus(); ReadUserData(); } /// /// MenuItem 到 MenuItemViewModel 的转换器 /// private Func MenuItemToViewModel => x => new MenuItemViewModel(_l[x.LocaleKey]) { Key = x.Key, IsActive = x.IsActive == true, Icon = string.IsNullOrWhiteSpace(x.Icon) ? null : StreamGeometry.Parse(x.Icon), CommandParameter = x.CommandParameter, //PageActions = x.PageActions, Items = x.Items.Select(MenuItemToViewModel).ToList(), MenuClickCommand = GetRelayCommand(x.CommandType), }; /// /// 根据命令类型返回中继命令 /// /// /// private IRelayCommand? GetRelayCommand(string? commandType) { if (!Enum.TryParse(commandType, out var cmdType)) { return null; } return cmdType switch { // 主题切换返回的中继命令 MenuClickCommandType.SwitchTheme => new RelayCommand((MenuItemViewModel? menuItem) => { var app = Application.Current; if (app is not null) { ThemeVariant? tv = menuItem?.CommandParameter switch { nameof(ThemeVariant.Default) => ThemeVariant.Default, nameof(ThemeVariant.Dark) => ThemeVariant.Dark, "Desert" => SemiTheme.Desert, "Dusk" => SemiTheme.Dusk, "NightSky" => SemiTheme.NightSky, _ => ThemeVariant.Default }; app.RequestedThemeVariant = tv; // 重载视图 _viewNavigator.ReloadCurrentPage(); } }), // 打开链接返回的中继命令 MenuClickCommandType.Link => new RelayCommand((MenuItemViewModel? menuItem) => { var url = menuItem?.CommandParameter; System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = url, UseShellExecute = true }); }), // 切换本地化语言 MenuClickCommandType.SwitchLanguage => new RelayCommand((MenuItemViewModel? menuItem) => { _l.CurrentCulture = _l.AvailableCultures.FirstOrDefault(f => f.IetfLanguageTag == menuItem?.CommandParameter) ?? Thread.CurrentThread.CurrentCulture; // 重载视图,触发本地化更新 _viewNavigator.ReloadCurrentPage(); LoadSettingMenus(); var app = Application.Current; if (app is null) return; CultureInfo cultureInfo = menuItem?.CommandParameter is string parameter ? new CultureInfo(parameter) : Thread.CurrentThread.CurrentCulture; Semi.Avalonia.SemiTheme.OverrideLocaleResources(app, cultureInfo); Ursa.Themes.Semi.SemiTheme.OverrideLocaleResources(app, cultureInfo); }), // 返回 null _ => null }; } /// /// 载入设置栏菜单 /// private void LoadSettingMenus() { var settingMenus = _menuItems.Where(x => x.Group == "Settings").Select(MenuItemToViewModel); SettingMenus = [.. settingMenus]; } private void ReadUserData() { var path = PathHelper.GetLocalFilePath(userFileName); if (File.Exists(path)) { var json = File.ReadAllText(path); var userData = JsonSerializer.Deserialize(json); if (userData != null) { RememberUserName = userData.IsRemember; if (RememberUserName) { UserName = userData.UserName; if (!string.IsNullOrEmpty(userData.Password)) { Password = DESHelper.Decrypt(userData.Password, "ZSL12345"); } } } } } private bool CanLogin() { ValidateAllProperties(); return !HasErrors; } [RelayCommand(CanExecute = nameof(CanLogin))] private async Task LoginAsync(object obj) { if (string.IsNullOrEmpty(UserName)) { ErrorMessage = _l["LoginWindow.UserNameEmpty"]; return; } if (string.IsNullOrEmpty(Password)) { ErrorMessage = _l["LoginWindow.PasseordEmpty"]; return; } var loginResult = await _accountService.LoginAsync(UserName, Password); if (loginResult.IsSuccess) { GlobalData.Instance.CurrentUser = loginResult.Data; //GlobalData.Instance.AddOrUpdate("UserName", UserName); GlobalData.Instance.AddOrUpdate("CurrentUser", loginResult.Data!.User); LoginSuccess = true; if (RememberUserName) { var userData = new UserData { UserName = UserName, Password = DESHelper.Encrypt(Password, "ZSL12345"), IsRemember = RememberUserName }; var json = JsonSerializer.Serialize(userData); var path = PathHelper.GetLocalFilePath(userFileName); await File.WriteAllTextAsync(path, json); } else { var path = PathHelper.GetLocalFilePath(userFileName); if (File.Exists(path)) { File.Delete(path); } } // 关闭登录窗口,并且 DialogResult返回True; if (obj is Window window) { window.Close(true); } //WeakReferenceMessenger.Default.Send(new LoginSuccessMessage(new UserItemViewModel { UserName = "Admin", IsActive = true })); } else { ErrorMessage = _l["LoginWindow.LoginFailed"]; } } [RelayCommand] private void ToggleTheme() { var app = Application.Current; if (app is null) return; var theme = app.ActualThemeVariant; app.RequestedThemeVariant = theme == ThemeVariant.Dark ? ThemeVariant.Light : ThemeVariant.Dark; } /// /// 获取项目文件中属性的值 /// /// Product属性字符串,如"Cowain WCS" public string GetProductName() { try { // 获取当前程序集(如果是其他项目,替换为对应程序集) Assembly assembly = Assembly.GetExecutingAssembly(); // 获取AssemblyProduct特性 var productAttribute = assembly.GetCustomAttribute(); // 返回值(为空时返回默认值) return productAttribute?.Product ?? "未知产品名称"; } catch (Exception ex) { // 异常处理(根据你的日志框架调整) _logger.LogError(ex, "读取Product属性失败"); return "未知产品名称"; } } } }