using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Serilog;
using System.ComponentModel;
using YZWater.Core.Models;
using YZWater.Core.Services;
namespace YZWater.Core.ViewModels;
///
/// 主窗口 ViewModel
///
public partial class MainViewModel : ObservableObject, IDisposable
{
private readonly ViewAViewModel _viewAViewModel;
private readonly ViewBViewModel _viewBViewModel;
private readonly ViewCViewModel _viewCViewModel;
private readonly ViewDViewModel _viewDViewModel;
private readonly ViewEViewModel _viewEViewModel;
private readonly ViewFViewModel _viewFViewModel;
private ProjectViewModel? _projectViewModel;
private readonly ThemeService _themeService = ThemeService.Instance;
private readonly LanguageService _langService = LanguageService.Instance;
private readonly SynchronizationContext? _uiContext = SynchronizationContext.Current;
private System.Timers.Timer? _clockTimer;
private bool _disposed;
[ObservableProperty]
private ObservableObject _currentView;
[ObservableProperty]
private string _title;
[ObservableProperty]
private string _currentTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
[ObservableProperty]
private bool _isPlcConnected;
[ObservableProperty]
private int _selectedTabIndex;
// 各 Tab 激活状态
[ObservableProperty] private bool _isTabAActive = true;
[ObservableProperty] private bool _isTabBActive;
[ObservableProperty] private bool _isTabCActive;
[ObservableProperty] private bool _isTabDActive;
[ObservableProperty] private bool _isTabEActive;
[ObservableProperty] private bool _isTabFActive;
// 当前 Tab 标题
[ObservableProperty] private string _tabTitle;
// 主题/语言状态
[ObservableProperty] private bool _isDarkTheme = true;
[ObservableProperty] private bool _isChinese = true;
[ObservableProperty] private string _themeIcon = "🌙";
[ObservableProperty] private string _langIcon = "中";
// 导航标签
[ObservableProperty] private string _navProcess;
[ObservableProperty] private string _navParams;
[ObservableProperty] private string _navFlow;
[ObservableProperty] private string _navAlarm;
[ObservableProperty] private string _navAbout;
[ObservableProperty] private string _navAudit;
// ═══ 用户管理翻译 ═══
[ObservableProperty] private string _userManageText;
[ObservableProperty] private string _createNewUserText;
[ObservableProperty] private string _userNameLabel;
[ObservableProperty] private string _passwordLabel;
[ObservableProperty] private string _displayNameLabel;
[ObservableProperty] private string _roleLabel;
[ObservableProperty] private string _statusLabel;
[ObservableProperty] private string _lastLoginLabel;
[ObservableProperty] private string _actionLabel;
[ObservableProperty] private string _createText;
[ObservableProperty] private string _closeText;
[ObservableProperty] private string _logoutText;
// ═══ 运行模式与连接状态 ═══
[ObservableProperty] private string _runMode = "Direct";
[ObservableProperty] private string _hubStatusText = "";
[ObservableProperty] private string _plcStatusText = "";
[ObservableProperty] private string _plcStatusColor = "#E74C3C";
// ═══ 子 ViewModel(供 View 绑定 DataContext) ═══
public ViewAViewModel ViewA => _viewAViewModel;
public ViewBViewModel ViewB => _viewBViewModel;
public ViewCViewModel ViewC => _viewCViewModel;
public ViewDViewModel ViewD => _viewDViewModel;
public ViewEViewModel ViewE => _viewEViewModel;
public ViewFViewModel ViewF => _viewFViewModel;
/// 项目化 ViewModel(当加载了项目档案时可用)
public ProjectViewModel? ProjectView => _projectViewModel;
/// 是否加载了项目档案
[ObservableProperty] private bool _hasProject;
// ═══ 用户与权限 ═══
[ObservableProperty] private string _currentUserName = string.Empty;
[ObservableProperty] private string _currentUserRole = string.Empty;
[ObservableProperty] private bool _canControl;
[ObservableProperty] private bool _canModifyParams;
[ObservableProperty] private bool _canManageUsers;
[ObservableProperty] private bool _showUserDialog;
public MainViewModel()
{
_viewAViewModel = new ViewAViewModel();
_viewBViewModel = new ViewBViewModel();
_viewCViewModel = new ViewCViewModel();
_viewDViewModel = new ViewDViewModel();
_viewEViewModel = new ViewEViewModel();
_viewFViewModel = new ViewFViewModel();
_currentView = _viewAViewModel;
UpdateAllTexts();
RefreshUserInfo();
LoadRunMode();
_langService.LanguageChanged += OnLanguageChanged;
_themeService.PropertyChanged += OnThemeServicePropertyChanged;
// PLC 连接状态监听
PlcPollingService.Instance.ConnectionStateChanged += OnConnectionStateChanged;
StartTimer();
// 项目档案初始化
InitializeProject();
}
///
/// 根据当前配置初始化项目 ViewModel
///
private void InitializeProject()
{
var profile = ProjectService.Current;
if (profile != null)
{
_projectViewModel = new ProjectViewModel(profile);
CurrentView = _projectViewModel;
HasProject = true;
Log.Information("已初始化项目视图: {Name}", profile.Name);
}
}
private void OnLanguageChanged()
{
RunOnUi(() =>
{
IsChinese = _langService.IsChinese;
UpdateAllTexts();
RefreshUserInfo();
});
}
private void OnThemeServicePropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != nameof(ThemeService.IsDarkTheme)) return;
RunOnUi(() =>
{
IsDarkTheme = _themeService.IsDarkTheme;
ThemeIcon = IsDarkTheme ? "🌙" : "☀️";
});
}
private void OnConnectionStateChanged(bool connected)
{
RunOnUi(() =>
{
PlcStatusText = connected ? _langService.Get("PlcConnectedStatus") : _langService.Get("PlcDisconnected");
PlcStatusColor = connected ? "#27AE60" : "#E74C3C";
IsPlcConnected = connected;
});
}
private void RunOnUi(Action action)
{
if (_disposed) return;
if (_uiContext != null && SynchronizationContext.Current != _uiContext)
_uiContext.Post(_ =>
{
if (!_disposed) action();
}, null);
else
action();
}
private void UpdateAllTexts()
{
Title = _langService.Get("AppName");
TabTitle = _langService.Get("ProcessFlow");
NavProcess = _langService.Get("NavProcess");
NavParams = _langService.Get("NavParams");
NavFlow = _langService.Get("NavFlow");
NavAlarm = _langService.Get("NavAlarm");
NavAbout = _langService.Get("NavAbout");
NavAudit = _langService.Get("AuditLog");
UserManageText = _langService.Get("UserManage");
CreateNewUserText = _langService.Get("CreateNewUser");
UserNameLabel = _langService.Get("UserName");
PasswordLabel = _langService.Get("Password");
DisplayNameLabel = _langService.Get("DisplayName");
RoleLabel = _langService.Get("Role");
StatusLabel = _langService.Get("Status");
LastLoginLabel = _langService.Get("LastLogin");
ActionLabel = _langService.Get("Action");
CreateText = _langService.Get("Create");
CloseText = _langService.Get("Close");
LogoutText = _langService.Get("Logout");
IsChinese = _langService.IsChinese;
LangIcon = IsChinese ? "中" : "EN";
IsDarkTheme = _themeService.IsDarkTheme;
ThemeIcon = IsDarkTheme ? "🌙" : "☀️";
}
///
/// 加载运行模式
///
private void LoadRunMode()
{
var config = ConfigService.GetConfig();
RunMode = config?.RunMode ?? "Direct";
HubStatusText = RunMode switch
{
"Server" => $"{_langService.Get("ServerMode")} :{config?.HubPort ?? 8765}",
"Client" => $"{_langService.Get("ClientMode")} → {config?.HubServerUrl ?? "ws://localhost:8765"}",
"Mock" => _langService.Get("MockMode"),
_ => _langService.Get("DirectMode")
};
}
[RelayCommand]
private void ToggleTheme()
{
_themeService.ToggleTheme();
}
[RelayCommand]
private void ToggleLanguage()
{
_langService.ToggleLanguage();
}
[RelayCommand]
private async Task ConnectPlcAsync() => await _viewAViewModel.ConnectPlcCommand.ExecuteAsync(null);
[RelayCommand]
private void DisconnectPlc() => _viewAViewModel.DisconnectPlcCommand.Execute(null);
[RelayCommand]
private async Task RefreshDataAsync() => await _viewAViewModel.RefreshDataCommand.ExecuteAsync(null);
// ─── Tab 切换 ───
private readonly string[] _tabTitleKeys = { "ProcessFlow", "Parameters", "FlowRecords", "AlarmLog", "About", "AuditLog" };
private void SetActiveTab(int index)
{
IsTabAActive = index == 0;
IsTabBActive = index == 1;
IsTabCActive = index == 2;
IsTabDActive = index == 3;
IsTabEActive = index == 4;
IsTabFActive = index == 5;
TabTitle = _langService.Get(_tabTitleKeys[index]);
}
[RelayCommand] private void ShowViewA()
{
CurrentView = HasProject && _projectViewModel != null
? _projectViewModel
: _viewAViewModel;
SetActiveTab(0);
}
[RelayCommand] private void ShowViewB() { CurrentView = _viewBViewModel; SetActiveTab(1); }
[RelayCommand] private void ShowViewC() { CurrentView = _viewCViewModel; SetActiveTab(2); }
[RelayCommand] private void ShowViewD() { CurrentView = _viewDViewModel; SetActiveTab(3); }
[RelayCommand] private void ShowViewE() { CurrentView = _viewEViewModel; SetActiveTab(4); }
[RelayCommand] private void ShowViewF() { CurrentView = _viewFViewModel; SetActiveTab(5); }
private void StartTimer()
{
_clockTimer = new System.Timers.Timer(1000);
_clockTimer.Elapsed += (s, e) =>
{
var time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
RunOnUi(() => CurrentTime = time);
};
_clockTimer.Start();
}
private void StopTimer()
{
_clockTimer?.Stop();
_clockTimer?.Dispose();
_clockTimer = null;
}
private void RefreshUserInfo()
{
var user = AuthService.CurrentUser;
if (user != null)
{
// 管理员显示名跟随语言更新
if (user.UserName == "admin")
{
var adminDisplayName = _langService.Get("AdminName");
if (user.DisplayName != adminDisplayName)
{
user.DisplayName = adminDisplayName;
DatabaseService.Db.Updateable(user).UpdateColumns(u => u.DisplayName).ExecuteCommand();
}
}
CurrentUserName = user.DisplayName;
CurrentUserRole = user.Role switch
{
UserRole.Viewer => _langService.Get("Viewer"),
UserRole.Operator => _langService.Get("OperatorRole"),
UserRole.Engineer => _langService.Get("Engineer"),
UserRole.Admin => _langService.Get("AdminRole"),
_ => "Unknown"
};
CanControl = AuthService.HasPermission(UserRole.Operator);
CanModifyParams = AuthService.HasPermission(UserRole.Engineer);
CanManageUsers = AuthService.HasPermission(UserRole.Admin);
}
}
[RelayCommand]
private void Logout()
{
AuthService.Logout();
}
[RelayCommand]
private void ToggleUserDialog()
{
ShowUserDialog = !ShowUserDialog;
if (ShowUserDialog)
{
LoadUsers();
}
}
// ═══ 用户管理 ═══
[ObservableProperty] private List _userList = new();
[ObservableProperty] private string _newUserName = string.Empty;
[ObservableProperty] private string _newUserPassword = string.Empty;
[ObservableProperty] private string _newUserDisplayName = string.Empty;
[ObservableProperty] private UserRole _newUserRole = UserRole.Operator;
[ObservableProperty] private string _userManageMessage = string.Empty;
private void LoadUsers()
{
UserList = AuthService.GetAllUsers();
}
[RelayCommand]
private void CreateUser()
{
if (string.IsNullOrWhiteSpace(NewUserName) || string.IsNullOrWhiteSpace(NewUserPassword))
{
UserManageMessage = _langService.Get("UserNamePasswordRequired");
return;
}
var (success, message) = AuthService.CreateUser(NewUserName, NewUserPassword, NewUserDisplayName, NewUserRole);
UserManageMessage = message;
if (success)
{
NewUserName = string.Empty;
NewUserPassword = string.Empty;
NewUserDisplayName = string.Empty;
NewUserRole = UserRole.Operator;
LoadUsers();
}
}
[RelayCommand]
private void ToggleUserActive(User? user)
{
if (user == null) return;
AuthService.SetUserActive(user.UserName, !user.IsActive);
LoadUsers();
}
public void Dispose()
{
if (_disposed) return;
_disposed = true;
StopTimer();
_langService.LanguageChanged -= OnLanguageChanged;
_themeService.PropertyChanged -= OnThemeServicePropertyChanged;
PlcPollingService.Instance.ConnectionStateChanged -= OnConnectionStateChanged;
_viewAViewModel.Dispose();
_viewBViewModel.Dispose();
_viewCViewModel.Dispose();
_viewDViewModel.Dispose();
_viewEViewModel.Dispose();
_viewFViewModel.Dispose();
_projectViewModel?.Dispose();
}
}