Sic03-8inch/SicUI/MainViewModel.cs

1180 lines
42 KiB
C#
Raw Normal View History

2023-03-03 15:42:13 +08:00
using Aitex.Core.Account;
using Aitex.Core.Common.DeviceData;
using Aitex.Core.WCF;
using Caliburn.Micro;
using MECF.Framework.Common.Account.Extends;
using MECF.Framework.Common.DataCenter;
using MECF.Framework.UI.Client.CenterViews.LogOnOff;
using MECF.Framework.UI.Client.ClientBase;
using MECF.Framework.UI.Core.Accounts;
using OpenSEMI.ClientBase;
using OpenSEMI.ClientBase.Command;
using OpenSEMI.ClientBase.Utility;
using SciChart.Charting.ChartModifiers;
using SciChart.Charting.Visuals;
using SciChart.Charting.Visuals.Annotations;
using SciChart.Charting.Visuals.Axes;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Threading;
using Sicentury.Core.Collections;
using System.Diagnostics;
using Caliburn.Micro.Core;
using MECF.Framework.Common.Account.Permissions;
using MECF.Framework.Common.MECF.Framework.Common.SCCore;
using MECF.Framework.UI.Client.ClientBase.Dialog;
using MECF.Framework.UI.Client.Core;
using MECF.Framework.UI.Client.Ctrlib.Controls;
2023-03-03 15:42:13 +08:00
namespace SicUI
2023-03-03 15:42:13 +08:00
{
public class MainViewModel : TimeredMainViewModel
2023-03-03 15:42:13 +08:00
{
#region Variables
2023-03-03 15:42:13 +08:00
private MainView _view;
private AppMenu _alarmMenu;
private AppMenu _currentMenuItem;
private List<AppMenu> _menuItems;
private List<AppMenu> _subMenuItems;
private ObservableCollection<AppMenu> _historyItems;
private string _context;
private bool _isReadOnlyMode;
private readonly IEventAggregator _eventAggregator;
private readonly IProgress<Credential> _prgShowLoginRequestConfirmDialog;
private CancellationTokenSource _ctsLoginRequestConfirmDialog;
2023-03-03 15:42:13 +08:00
#endregion
2023-03-03 15:42:13 +08:00
#region Constructors
2023-03-03 15:42:13 +08:00
2024-03-18 17:57:54 +08:00
public MainViewModel(IEventAggregator eventAggregator)
2023-03-03 15:42:13 +08:00
{
BaseApp.Instance.Initialize();
((ClientApp)BaseApp.Instance).ViewModelSwitcher = this;
_eventAggregator = eventAggregator;
2023-03-03 15:42:13 +08:00
//for login part
Roles = RoleAccountProvider.Instance.GetRoles();
2023-03-03 15:42:13 +08:00
EventLogList = new DelayedPresentRollingObservableCollection<EventItem>(1000);
EventLogsView = CollectionViewSource.GetDefaultView(EventLogList);
2023-03-03 15:42:13 +08:00
//WarnEventLogList = new ObservableCollection<EventItem>();
2023-03-03 15:42:13 +08:00
SoftwareVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
2023-03-03 15:42:13 +08:00
EventClient.Instance.OnEvent += Instance_OnEvent;
EventClient.Instance.OnDisconnectedWithRT += Instance_OnDisconnectedWithRT;
EventClient.Instance.Start();
2023-03-03 15:42:13 +08:00
IsPM1Installed = (bool)QueryDataClient.Instance.Service.GetConfig("System.SetUp.IsPM1Installed");
IsPM2Installed = (bool)QueryDataClient.Instance.Service.GetConfig("System.SetUp.IsPM2Installed");
IsBufferInstalled = (bool)QueryDataClient.Instance.Service.GetConfig("System.SetUp.IsBufferInstalled");
IsLLInstalled = (bool)QueryDataClient.Instance.Service.GetConfig("System.SetUp.IsLoadLockInstalled");
2023-03-03 15:42:13 +08:00
_prgShowLoginRequestConfirmDialog = new Progress<Credential>(ShowLoginRequestConfirmDialog);
2023-03-03 15:42:13 +08:00
Reset();
2023-03-03 15:42:13 +08:00
}
#endregion
2023-03-03 15:42:13 +08:00
#region Menus
public string NowDateTime { get; set; }
private bool _IsLogin = false;
public bool IsLogin
{
get => _IsLogin;
set { _IsLogin = value; NotifyOfPropertyChange(); }
2023-03-03 15:42:13 +08:00
}
private List<Role> roles;
public List<Role> Roles
{
2024-03-18 17:57:54 +08:00
get => roles;
set { roles = value; RaisePropertyChangedEventImmediately("Roles"); }
2023-03-03 15:42:13 +08:00
}
private ICommand menuItemClickCommand;
public ICommand MenuItemClickCommand
{
get
{
2024-03-18 17:57:54 +08:00
if (menuItemClickCommand == null)
menuItemClickCommand = new BaseCommand<AppMenu>((AppMenu menuViewItem) => SwitchMenuItem(menuViewItem));
return menuItemClickCommand;
2023-03-03 15:42:13 +08:00
}
}
private ICommand mainmenuItemClickCommand;
public ICommand MainMenuItemClickCommand
{
get
{
2024-03-18 17:57:54 +08:00
if (mainmenuItemClickCommand == null)
mainmenuItemClickCommand = new BaseCommand<AppMenu>((AppMenu menuViewItem) => MainSwitchMenuItem(menuViewItem));
return mainmenuItemClickCommand;
2023-03-03 15:42:13 +08:00
}
}
public List<AppMenu> MenuItems
{
get => _menuItems;
2024-03-18 17:57:54 +08:00
set { _menuItems = value; NotifyOfPropertyChange(); }
2023-03-03 15:42:13 +08:00
}
public List<AppMenu> SubMenuItems
{
get => _subMenuItems;
2024-03-18 17:57:54 +08:00
set { _subMenuItems = value; NotifyOfPropertyChange(); }
2023-03-03 15:42:13 +08:00
}
public ObservableCollection<AppMenu> HistoryMenus
{
get => _historyItems;
2024-03-18 17:57:54 +08:00
set { _historyItems = value; NotifyOfPropertyChange(); }
2023-03-03 15:42:13 +08:00
}
public string Context
{
get => _context;
2024-03-18 17:57:54 +08:00
set { _context = value; NotifyOfPropertyChange(); }
2023-03-03 15:42:13 +08:00
}
public BaseModel CurrentViewModel { get; private set; }
public UserContext User => BaseApp.Instance.UserContext;
2023-03-03 15:42:13 +08:00
#endregion
public bool IsPM1Installed { get; set; }
public bool IsPM2Installed { get; set; }
public bool IsBufferInstalled { get; set; }
public bool IsLLInstalled { get; set; }
public bool IsPermission { get; set; }
public bool IsAutoLogout { get; set; }
public int LogoutTime { get; set; }
public bool IsReadOnlyMode
{
get => _isReadOnlyMode;
set
{
_isReadOnlyMode = value;
NotifyOfPropertyChange();
if (_isReadOnlyMode)
{
BaseApp.Instance.UserMode = UserMode.ReadOnly;
// 通知RecipeEditor视图或PMProcess视图锁定Recipe
_eventAggregator.PublishOnUIThread(CommonAggregateEvents.EnterReadOnlyMode);
}
}
}
2023-03-03 15:42:13 +08:00
//public ObservableCollection<EventItem> WarnEventLogList { get; set; }
private DelayedPresentRollingObservableCollection<EventItem> EventLogList { get; }
/// <summary>
/// 用于在主界面显示Event Log的视图。
/// 通过该视图筛选IsAlarm条目。
/// </summary>
public ICollectionView EventLogsView { get; }
private bool _isShowAlarmEventOnly;
/// <summary>
/// IsAlarm CheckBox绑定到这里直接从<see cref="EventLogsView"/>中过滤所需的数据。
/// </summary>
public bool IsShowAlarmEventOnly
{
get => _isShowAlarmEventOnly;
set
{
_isShowAlarmEventOnly = value;
if (_isShowAlarmEventOnly)
{
EventLogsView.Filter = item =>
{
if (item is EventItem ei)
{
return ei.Level == EventLevel.Alarm;
}
return false;
};
}
else
{
EventLogsView.Filter = null;
}
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsShowAlarmEventOnly)));
}
}
public Visibility AllEventsVisibility { get; set; }
public Visibility WarnEventsVisibility { get; set; }
[Subscription("PM1.IsBypassInterlock")]
public bool IsPM1InterlockBypassed { get; set; }
[Subscription("PM1.IsBypassEnableTable")]
public bool IsPM1EnableTableBypassed { get; set; }
public bool IsPM1Warning => IsPM1InterlockBypassed || IsPM1EnableTableBypassed;
public string PM1WarningMessage
{
get
{
if (IsPM1InterlockBypassed && IsPM1EnableTableBypassed)
return "PM1 Interlock and Enable Table are bypassed";
if (IsPM1InterlockBypassed)
return "PM1 Interlock is bypassed";
return "PM1 Enable Table is bypassed";
}
}
[Subscription("PM2.IsBypassInterlock")]
public bool IsPM2InterlockBypassed { get; set; }
[Subscription("PM2.IsBypassEnableTable")]
public bool IsPM2EnableTableBypassed { get; set; }
public bool IsPM2Warning => IsPM2InterlockBypassed || IsPM2EnableTableBypassed;
public string PM2WarningMessage
{
get
{
if (IsPM2InterlockBypassed && IsPM2EnableTableBypassed)
return "PM2 Interlock and Enable Table are bypassed";
if (IsPM2InterlockBypassed)
return "PM2 Interlock is bypassed";
return "PM2 Enable Table is bypassed";
}
}
[Subscription("TM.IsBypassInterlock")]
public bool IsTMInterlockBypassed { get; set; }
[Subscription("TM.IsBypassEnableTable")]
public bool IsTMEanbleTableBypassed { get; set; }
public bool IsTMWarning => IsTMInterlockBypassed || IsTMEanbleTableBypassed;
public string TMWarningMessage
{
get
{
if (IsTMInterlockBypassed && IsTMEanbleTableBypassed)
return "TM Interlock and Enable Table are bypassed";
if (IsTMInterlockBypassed)
return "TM Interlock is bypassed";
return "TM Enable Table is bypassed";
}
}
2023-03-03 16:45:39 +08:00
2023-03-03 15:42:13 +08:00
[Subscription("Rt.Status")]
public string RtStatus { get; set; }
public string RtStatusBackground => ModuleStatusBackground.GetStatusBackground(RtStatus);
[Subscription("System.ControlStatus")]
public string ControlStatus { get; set; }
[Subscription("System.CommunicationStatus")]
public string HostStatus { get; set; }
public string HostStatusBackground
{
get
{
switch (HostStatus)
{
case "Disabled":
return "Yellow";
case "Enabled":
case "EnabledNotCommunicating":
case "WaitCRA":
case "WaitDelay":
case "WaitCRFromHost":
return "Transparent";
case "EnabledCommunicating":
return "LawnGreen";
default:
return "Yellow";
}
}
}
[Subscription("PM1.Status")]
public string _PM1Status { get; set; }
public string PM1Status
{
get
{
if (IsPM1Installed)
return _PM1Status;
else
return "NotInstall";
}
set => _PM1Status = value;
2023-03-03 15:42:13 +08:00
}
public string PM1StatusBackground => ModuleStatusBackground.GetStatusBackground(PM1Status);
2023-03-03 15:42:13 +08:00
[Subscription("PM2.Status")]
public string _PM2Status { get; set; }
public string PM2Status
{
get
{
if (IsPM2Installed)
return _PM2Status;
else
return "NotInstall";
}
set => _PM2Status = value;
2023-03-03 15:42:13 +08:00
}
public string PM2StatusBackground => ModuleStatusBackground.GetStatusBackground(PM2Status);
2023-03-03 15:42:13 +08:00
[Subscription("Aligner.Status")]
public string AlignerStatus { get; set; }
public string AlignerStatusBackground => ModuleStatusBackground.GetStatusBackground(AlignerStatus);
2023-03-03 15:42:13 +08:00
[Subscription("CassAL.Status")]
public string CassALStatus { get; set; }
public string CassALStatusBackground => ModuleStatusBackground.GetStatusBackground(CassALStatus);
2023-03-03 15:42:13 +08:00
[Subscription("CassAR.Status")]
public string CassARStatus { get; set; }
public string CassARStatusBackground => ModuleStatusBackground.GetStatusBackground(CassARStatus);
2023-03-03 15:42:13 +08:00
[Subscription("CassBL.Status")]
public string CassBLStatus { get; set; }
public string CassBLStatusBackground => ModuleStatusBackground.GetStatusBackground(CassBLStatus);
2023-03-03 15:42:13 +08:00
[Subscription("UnLoad.Status")]
public string UnLoadStatus { get; set; }
public string UnLoadStatusBackground => ModuleStatusBackground.GetStatusBackground(UnLoadStatus);
2023-03-03 15:42:13 +08:00
[Subscription("EFEM.Status")]
public string EFEMStatus { get; set; }
public string EFEMStatusBackground => ModuleStatusBackground.GetStatusBackground(EFEMStatus);
2023-03-03 15:42:13 +08:00
[Subscription("Buffer.Status")]
public string BufferStatus { get; set; }
public string BufferStatusBackground => ModuleStatusBackground.GetStatusBackground(BufferStatus);
2023-03-03 15:42:13 +08:00
[Subscription("LoadLock.Status")]
public string LLStatus { get; set; }
public string LLStatusBackground => ModuleStatusBackground.GetStatusBackground(LLStatus);
2023-03-03 15:42:13 +08:00
[Subscription("TM.Status")]
public string TMStatus { get; set; }
public string TMStatusBackground => ModuleStatusBackground.GetStatusBackground(TMStatus);
2023-03-03 15:42:13 +08:00
[Subscription("WaferRobot.Status")]
public string WaferRobotStatus { get; set; }
public string WaferRobotStatusBackground => ModuleStatusBackground.GetStatusBackground(WaferRobotStatus);
2023-03-03 15:42:13 +08:00
[Subscription("TrayRobot.Status")]
public string TrayRobotStatus { get; set; }
public string TrayRobotStatusBackground => ModuleStatusBackground.GetStatusBackground(TrayRobotStatus);
2023-03-03 15:42:13 +08:00
[Subscription("System.IsOnline")]
public bool IsOnlineSystem { get; set; }
[Subscription("PM1.IsOnline")]
public bool IsOnlinePM1 { get; set; }
[Subscription("PM2.IsOnline")]
public bool IsOnlinePM2 { get; set; }
[Subscription("EFEM.IsOnline")]
public bool IsOnlineEFEM { get; set; }
[Subscription("Aligner.IsOnline")]
public bool IsOnlineAligner { get; set; }
[Subscription("CassAL.IsOnline")]
public bool IsOnlineCassAL { get; set; }
[Subscription("CassBL.IsOnline")]
public bool IsOnlineCassBL { get; set; }
[Subscription("CassAR.IsOnline")]
public bool IsOnlineCassAR { get; set; }
[Subscription("UnLoad.IsOnline")]
public bool IsOnlineUnLoad { get; set; }
[Subscription("LoadLock.IsOnline")]
public bool IsOnlineLL { get; set; }
[Subscription("TM.IsOnline")]
public bool IsOnlineTM { get; set; }
[Subscription("Buffer.IsOnline")]
public bool IsOnlineBuffer { get; set; }
[Subscription("WaferRobot.IsOnline")]
public bool IsOnlineWaferRobot { get; set; }
[Subscription("TrayRobot.IsOnline")]
public bool IsOnlineTrayRobot { get; set; }
[Subscription("PM1.SignalTower.DeviceData")]
public AITSignalTowerData SignalTowerData { get; set; }
public string SoftwareVersion
{
get;
set;
}
public string RunTime => DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
2023-03-03 15:42:13 +08:00
[Subscription("System.HasActiveAlarm")]
public bool SystemHasAlarm { get; set; }
private void Instance_OnDisconnectedWithRT()
{
MessageBox.Show("Disconnected with RT, UI will exit", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
Environment.Exit(0);
}
public void ShowAlarmEvents()
{
AllEventsVisibility = Visibility.Hidden;
WarnEventsVisibility = Visibility.Visible;
2024-03-18 17:57:54 +08:00
NotifyOfPropertyChange("AllEventsVisibility");
NotifyOfPropertyChange("WarnEventsVisibility");
2023-03-03 15:42:13 +08:00
}
public void ShowAllEvents()
{
AllEventsVisibility = Visibility.Visible;
WarnEventsVisibility = Visibility.Hidden;
2024-03-18 17:57:54 +08:00
NotifyOfPropertyChange("AllEventsVisibility");
NotifyOfPropertyChange("WarnEventsVisibility");
2023-03-03 15:42:13 +08:00
}
private void Instance_OnEvent(EventItem obj)
{
switch (obj.Type)
{
case EventType.EventUI_Notify:
LogEvent(obj);
break;
case EventType.Dialog_Nofity:
//PopDialog(obj);
break;
case EventType.KickOut_Notify:
if (obj.Description == "ShutDown")
{
AccountClient.Instance.Service.LogoutEx(BaseApp.Instance.UserContext.Token);
2023-03-03 15:42:13 +08:00
ShutdownThread = ShutdownExecute;
ShutdownThread.BeginInvoke(ShutdownCallBack, ShutdownThread);
}
break;
case EventType.Sound_Notify:
break;
case EventType.UIMessage_Notify:
//PopUIMessage(obj);
break;
}
}
private void LogEvent(EventItem obj)
{
if (obj.Type != EventType.EventUI_Notify)
return;
EventLogList.Add(obj);
}
public void SetModuleOnline(object sender, RoutedEventArgs args)
{
if (sender is ModuleStatusIndicator indicator)
{
if (indicator.HasWarning)
{
DialogBox.ShowError($"Unable to set {indicator.Caption} online since {indicator.WarningTip}");
return;
}
2023-03-03 15:42:13 +08:00
if (MessageBoxResult.Yes == MessageBox.Show($"Set {indicator.Caption} Online?", "", MessageBoxButton.YesNo, MessageBoxImage.Warning))
InvokeClient.Instance.Service.DoOperation($"{indicator.ModuleName}.SetOnline");
}
}
public void SetModuleOffline(object sender, RoutedEventArgs args)
{
if (sender is ModuleStatusIndicator indicator)
{
if (MessageBoxResult.Yes == MessageBox.Show($"Set {indicator.Caption} Offline?", "", MessageBoxButton.YesNo, MessageBoxImage.Warning))
{
InvokeClient.Instance.Service.DoOperation($"{indicator.ModuleName}.SetOffline");
}
}
}
public void Reset()
{
InvokeClient.Instance.Service.DoOperation("System.Reset");
}
public void BuzzerOff()
{
InvokeClient.Instance.Service.DoOperation($"System.AckAllAlarms");
}
#region Login/Logout Operations
private Task<LoginResult> _loginTask;
private LoginRequestWaitDialog _loginWaitDialog = null;
/// <summary>
/// 密码输入框中按下Enter键。
/// </summary>
/// <param name="args"></param>
/// <param name="loginName"></param>
/// <param name="password"></param>
/// <param name="role"></param>
public void PasswordBoxEnterKeyPressed(KeyEventArgs args, string loginName, PasswordBox password, Role role)
2023-03-03 15:42:13 +08:00
{
if (args.Key == Key.Enter)
RequestLogin(loginName, password, role);
2023-03-03 15:42:13 +08:00
}
/// <summary>
/// 显示远程登录请求确认对话框。
/// </summary>
/// <param name="credRequesting">正在请求登录的凭据</param>
private void ShowLoginRequestConfirmDialog(Credential credRequesting)
2023-03-03 15:42:13 +08:00
{
var dlgConfirm = new LoginRequestConfirmationDialog(credRequesting, _ctsLoginRequestConfirmDialog)
2023-03-03 15:42:13 +08:00
{
Owner = Application.Current.MainWindow
};
var retDlg = dlgConfirm.ShowDialog();
if (retDlg == true)
{
AccountClient.Instance.Service.ConfirmLoginRequest(credRequesting.AccountInfo.LoginName);
var role = BaseApp.Instance.UserContext.Role;
Logoff();
// 降级为仅查看模式
IsReadOnlyMode = true;
BaseApp.Instance.UserContext.Role = role;
BaseApp.Instance.UserContext.Credential = Credential.ReadOnlyOne;
}
else
{
AccountClient.Instance.Service.RejectLoginRequest(credRequesting.AccountInfo.LoginName);
}
}
2023-03-03 15:42:13 +08:00
/// <summary>
/// 显示登录确认等待对话框。
/// </summary>
/// <param name="cts"></param>
/// <returns></returns>
private Task ShowRequestLoginWaiter(CancellationTokenSource cts)
{
var ct = cts.Token;
2023-03-03 15:42:13 +08:00
return Task.Run(() =>
{
/*bool? waitResult = null;*/
2023-03-03 15:42:13 +08:00
// 如果超过一定时间没有从RT返回确认信息则显示登录中的提示
Thread.Sleep(500);
2023-03-03 15:42:13 +08:00
if (ct.IsCancellationRequested)
return;
2023-03-03 15:42:13 +08:00
Execute.OnUIThread(() =>
{
_loginWaitDialog = new LoginRequestWaitDialog()
{
Owner = Application.Current.MainWindow
};
_loginWaitDialog.ShowDialog();
});
2023-03-03 15:42:13 +08:00
/*while (true)
{
Thread.Sleep(500);
// 等待对话框关闭不关心返回的DialogResult
// 关闭原因:
// 1. 点击Cancel按钮
// 2. 超时
// 3. 远端接受或拒绝请求
if (waitResult.HasValue)
break;
if (ct.IsCancellationRequested)
break;
2023-03-03 15:42:13 +08:00
}
// 强制关闭等待对话框
Execute.OnUIThread(() =>
2023-03-03 15:42:13 +08:00
{
loginWaitDialog?.Close();
});*/
}, ct);
}
public async void RequestLogin(string loginName, PasswordBox password, Role role)
{
if (_loginTask is { Status: TaskStatus.Running })
return;
#region Validate Parameters
if (string.IsNullOrEmpty(loginName))
{
DialogBox.ShowError("User Name can not be empty.");
return;
}
if (string.IsNullOrEmpty(password.Password))
{
DialogBox.ShowError("Password can not be empty.");
return;
}
if (role == null || string.IsNullOrEmpty(role.RoleId))
{
DialogBox.ShowError("Role can not be empty.");
return;
}
2023-03-03 15:42:13 +08:00
#endregion
2023-03-03 15:42:13 +08:00
// 向RT请求登录
try
{
var ctsWaitingTask = new CancellationTokenSource();
var taskWaiting = ShowRequestLoginWaiter(ctsWaitingTask);
_loginTask = AccountClient.Instance.Service.LoginEx(loginName, password.Password, role?.RoleId ?? "",
BaseApp.Instance.ClientInfo);
// 等待确认超时,或已被接受/拒绝登录
await Task.WhenAny(_loginTask, taskWaiting);
if (_loginTask.Status == TaskStatus.RanToCompletion)
{
// 被接受或拒绝登录
ctsWaitingTask.Cancel();
_loginWaitDialog?.Close();
switch (_loginTask.Result.Result)
2023-03-03 15:42:13 +08:00
{
case LoginRequestResults.Error:
DialogBox.ShowError("Error occurred when login, see log for details.");
2023-03-03 15:42:13 +08:00
break;
case LoginRequestResults.WrongPwd:
2023-03-03 15:42:13 +08:00
DialogBox.ShowError("Invalid password.");
break;
case LoginRequestResults.NoMatchRole:
DialogBox.ShowError("The user does not belong to the role.");
2023-03-03 15:42:13 +08:00
break;
case LoginRequestResults.NoMatchUser:
DialogBox.ShowError("The user is not found.");
2023-03-03 15:42:13 +08:00
break;
case LoginRequestResults.Rejected:
DialogBox.ShowError("Login Request is rejected.");
break;
case LoginRequestResults.RequstingLogin:
DialogBox.ShowError(
"The same user is requesting to login from other place, please try again later.");
break;
case LoginRequestResults.Timeout:
DialogBox.ShowError("Timeout to wait login request confirmation.");
break;
case LoginRequestResults.Confirmed:
var cred = _loginTask.Result.Credential;
BaseApp.Instance.UserMode = UserMode.Normal;
BaseApp.Instance.UserContext.Credential = cred;
BaseApp.Instance.UserContext.Role = role;
BaseApp.Instance.UserContext.LastAccessTime = DateTime.Now;
BaseApp.Instance.UserContext.IsLogin = true;
//Load menu by role
//filer menu if necessary...
BaseApp.Instance.MenuManager.LoadMenu(
RoleAccountProvider.Instance.GetAccessibleMenusByRole(role.RoleId));
IsAutoLogout = role.IsAutoLogout;
LogoutTime = role.LogoutTime;
IsPermission = RoleAccountProvider.Instance.GetMenuPermission(role.RoleId, "Header") == MenuPermissionEnum.MP_READ_WRITE;
InitMenu(); //bind menu to main view
IsLogin = true; //control the display logic of main view
IsReadOnlyMode = false;
LOG.Info($"{loginName} login as {role.RoleName}");
2023-03-03 15:42:13 +08:00
break;
default:
DialogBox.ShowError("Unknown login result, see log for details.");
2023-03-03 15:42:13 +08:00
break;
}
}
else if (taskWaiting.Status == TaskStatus.RanToCompletion)
{
// 等待确认超时
// 注意该请求在RT的存活时间比UI超时时间长因此需要显式取消请求否则下次登录请求需要等CredentialManager超时后才能重新发起
AccountClient.Instance.Service.CancelLoginRequest(loginName);
}
else
{
// 两个任务均失败显式调用下列方法强制RT清理凭据。
AccountClient.Instance.Service.CancelLoginRequest(loginName);
2023-03-03 15:42:13 +08:00
}
}
catch (InvalidOperationException ex)
2023-03-03 15:42:13 +08:00
{
LOG.Error(ex.Message);
2023-03-03 15:42:13 +08:00
}
catch (Exception ex)
2023-03-03 15:42:13 +08:00
{
LOG.Error(ex.Message);
2023-03-03 15:42:13 +08:00
}
}
public void ShowLogoutDialog()
2023-03-03 15:42:13 +08:00
{
if (!IsReadOnlyMode)
2023-03-03 15:42:13 +08:00
{
var windowManager = new WindowManager();
var logoffViewmodel = new LogoffViewModel();
windowManager.ShowDialog(logoffViewmodel);
2023-03-03 15:42:13 +08:00
BaseApp.Instance.UserMode = logoffViewmodel.DialogResult;
2023-03-03 15:42:13 +08:00
switch (logoffViewmodel.DialogResult)
{
case UserMode.Logoff:
Logoff();
break;
case UserMode.Exit:
AccountClient.Instance.Service.LogoutEx(BaseApp.Instance.UserContext.Token);
BaseApp.Instance.UserMode = UserMode.Exit;
LOG.Info($"{BaseApp.Instance.UserContext.LoginName} exit as {BaseApp.Instance.UserContext.Role.RoleName}");
TryClose();
break;
case UserMode.Shutdown:
//配置立即生效。
var roleId = BaseApp.Instance.UserContext.Role.RoleId;
var canShutDown =
RoleAccountProvider.Instance.GetMenuPermission(roleId, "Operation.Behaviour.ShutDown") ==
MenuPermissionEnum.MP_READ_WRITE;
if (canShutDown)
InvokeClient.Instance.Service.DoOperation("System.ShutDown");
else
{
DialogBox.ShowError("No Permission for ShutDown");
}
2023-03-03 15:42:13 +08:00
break;
}
2023-03-03 15:42:13 +08:00
_eventAggregator.PublishOnUIThread(logoffViewmodel.DialogResult);
}
else
2023-03-03 15:42:13 +08:00
{
Logoff();
IsReadOnlyMode = false;
2023-03-03 15:42:13 +08:00
}
}
public void Logoff()
{
BaseApp.Instance.UserMode = UserMode.Logoff;
if (BaseApp.Instance.UserContext.IsLogin)
{
try
{
AccountClient.Instance.Service.LogoutEx(BaseApp.Instance.UserContext.Token);
LOG.Info(
$"{BaseApp.Instance.UserContext.LoginName} logoff as {BaseApp.Instance.UserContext.Role.RoleName}");
BaseApp.Instance.UserContext.Clear();
ClearItems();
2023-03-03 15:42:13 +08:00
}
catch (Exception exp)
{
LOG.Write(exp);
}
}
IsLogin = false; //no independent login page
Roles = RoleAccountProvider.Instance.GetRoles();
}
#endregion
2023-03-03 15:42:13 +08:00
#region override functions
public override void CanClose(Action<bool> callback)
{
if (BaseApp.Instance.UserMode == UserMode.Normal)
{
callback(false);
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, (ThreadStart)ShowLogoutDialog);
2023-03-03 15:42:13 +08:00
}
else
callback(true);
}
protected override void OnInitialize()
{
//display system version or other info...
2024-03-18 17:57:54 +08:00
DisplayName = "Sic Auto-GE";
2023-03-03 15:42:13 +08:00
base.OnInitialize();
2024-03-18 17:57:54 +08:00
StartTimer();
2023-03-03 15:42:13 +08:00
2023-03-03 15:42:13 +08:00
}
protected override void OnActivate()
{
base.OnActivate();
2024-03-18 17:57:54 +08:00
ShowAllEvents();
2023-03-03 15:42:13 +08:00
EnableTimer(true);
List<ConfigChangedInfo> s = (List<ConfigChangedInfo>)QueryDataClient.Instance.Service.GetConfig("SystemConfig.DataChangedList");
if (s != null && s.Count > 0)
{
string tips = "";
foreach (var t in s)
{
var value = QueryDataClient.Instance.Service.GetConfig(t.Name);
if (value != null)
{
tips += t.Name + (t.Enable ? " " : " HAS ") + "CHANGED:\r\n(Previous)\t" + t.OldValue + " => " + value.ToString() + "\t(Latest)\r\n";
}
}
if (tips != "")
{
DialogBox.ShowInfo("There are some changes in SystemConfig,\r\n" +
"please make sure those changes are OK:\r\n" +
"****************************************************\r\n" + tips);
InvokeClient.Instance.Service.DoOperation("SystemConfig.Confirm");
}
}
if (Debugger.IsAttached)
{
RequestLogin("admin", new PasswordBox() { Password = "admin" }, new Role("0", "Manager", false, 1000, null));
}
2023-03-03 15:42:13 +08:00
}
void DrawSciChart()
{
// Create the chart surface
var sciChartSurface = new SciChartSurface();
// Create the X and Y Axis
var xAxis = new NumericAxis() { AxisTitle = "Number of Samples (per series)" };
var yAxis = new NumericAxis() { AxisTitle = "Value" };
sciChartSurface.XAxis = xAxis;
sciChartSurface.YAxis = yAxis;
// Specify Interactivity Modifiers
sciChartSurface.ChartModifier = new ModifierGroup(new RubberBandXyZoomModifier(), new ZoomExtentsModifier());
// Add annotation hints to the user
var textAnnotation = new TextAnnotation()
{
Text = "Hello World!",
X1 = 5.0,
Y1 = 5.0
};
sciChartSurface.Annotations.Add(textAnnotation);
}
protected override void OnViewLoaded(object view)
{
base.OnViewLoaded(view);
2024-03-18 17:57:54 +08:00
_view = view as MainView;
_view.tbLoginName.Focus();
2023-03-03 15:42:13 +08:00
_view.SplashScreen?.Complete();
}
protected override void OnDeactivate(bool close)
{
base.OnDeactivate(close);
EnableTimer(false);
}
#endregion
#region
#region Sync ShutDown Thread
public delegate void ShutDownSysncThread();
ShutDownSysncThread ShutdownThread = null;
ShutdownViewModel ShutdownWindow = null;
private void ShutdownExecute()
{
BaseApp.Instance.UserMode = UserMode.Shutdown;
BaseApp.Instance.UserContext.IsLogin = false;
LOG.Info($"{BaseApp.Instance.UserContext.LoginName} shutdown as {BaseApp.Instance.UserContext.Role.RoleName}");
2023-03-03 15:42:13 +08:00
2024-03-18 17:57:54 +08:00
TryClose();
2023-03-03 15:42:13 +08:00
}
private void ShutdownCallBack(IAsyncResult result)
{
if (ShutdownWindow != null)
{
ShutdownWindow.TryClose();
}
ShutdownThread.EndInvoke(result);
}
#endregion
#region Menu Control and page switch
private void InitMenu()
{
2024-03-18 17:57:54 +08:00
MenuItems = BaseApp.Instance.MenuManager.MenuItems;
SubMenuItems = new List<AppMenu>();
HistoryMenus = new ObservableCollection<AppMenu>();
2023-03-03 15:42:13 +08:00
2024-03-18 17:57:54 +08:00
if (MenuItems.Count > 0)
2023-03-03 15:42:13 +08:00
{
AppMenu _default = null;
2024-03-18 17:57:54 +08:00
foreach (AppMenu menuitem in MenuItems)
2023-03-03 15:42:13 +08:00
{
if (menuitem.MenuItems.Count > 0)
{
if (menuitem.AlarmModule == "System")
{
_alarmMenu = menuitem;
break;
}
if (_default == null)
_default = menuitem.MenuItems[0];
}
}
2024-03-18 17:57:54 +08:00
SwitchMenuItem(_default);
2023-03-03 15:42:13 +08:00
}
}
public void MainSwitchMenuItem(AppMenu menuViewItem)
{
if (menuViewItem.MenuItems.Count > 0)
{
if (menuViewItem.LastSelectedSubMenu != null)
SwitchMenuItem(menuViewItem.LastSelectedSubMenu);
else
SwitchMenuItem(menuViewItem.MenuItems[0]);
}
}
public void SwitchMenuItem(AppMenu menuViewItem)
{
2024-03-18 17:57:54 +08:00
if (!string.IsNullOrEmpty(menuViewItem.ViewModel))
2023-03-03 15:42:13 +08:00
{
if (menuViewItem.Model == null)
{
menuViewItem.Model =
(BaseModel)AssemblyUtil.CreateInstance(AssemblyUtil.GetType(menuViewItem.ViewModel));
2023-03-03 15:42:13 +08:00
((BaseModel)menuViewItem.Model).Permission = menuViewItem.Permission;
if (menuViewItem.Model is ISupportMultipleSystem smsViewModel)
smsViewModel.SystemName = menuViewItem.System;
}
2023-03-03 15:42:13 +08:00
2024-03-18 17:57:54 +08:00
ActivateItem(((BaseModel)menuViewItem.Model));
2023-03-03 15:42:13 +08:00
CurrentViewModel = ((BaseModel)menuViewItem.Model);
//if (((BaseModel)menuViewItem.Model).Page != PageID.MAX_PAGE)
// BaseApp.Instance.SetCurrentPage(((BaseModel)menuViewItem.Model).Page);
2024-03-18 17:57:54 +08:00
HandleSubAndHistoryMenu(menuViewItem);
2023-03-03 15:42:13 +08:00
2024-03-18 17:57:54 +08:00
if (_currentMenuItem != null)
2023-03-03 15:42:13 +08:00
{
2024-03-18 17:57:54 +08:00
_currentMenuItem.Selected = false;
_currentMenuItem.Parent.Selected = false;
2023-03-03 15:42:13 +08:00
}
menuViewItem.Selected = true;
menuViewItem.Parent.Selected = true;
menuViewItem.Parent.LastSelectedSubMenu = menuViewItem;
2024-03-18 17:57:54 +08:00
_currentMenuItem = menuViewItem;
2023-03-03 15:42:13 +08:00
}
}
private void HandleSubAndHistoryMenu(AppMenu menuitem)
{
2024-03-18 17:57:54 +08:00
SubMenuItems = menuitem.Parent.MenuItems;
2023-03-03 15:42:13 +08:00
2024-03-18 17:57:54 +08:00
if (!HistoryMenus.Contains(menuitem))
2023-03-03 15:42:13 +08:00
{
2024-03-18 17:57:54 +08:00
if (HistoryMenus.Count >= 8)
HistoryMenus.RemoveAt(7);
HistoryMenus.Insert(0, menuitem);
2023-03-03 15:42:13 +08:00
}
else
{
2024-03-18 17:57:54 +08:00
HistoryMenus.Remove(menuitem);
HistoryMenus.Insert(0, menuitem);
2023-03-03 15:42:13 +08:00
}
}
#endregion
#region Refresh Date Time on page
protected override void InvokeAfterUpdateProperty(Dictionary<string, object> data)
{
if (_alarmMenu != null)
_alarmMenu.IsAlarm = SystemHasAlarm;
}
protected override bool OnTimer()
{
try
{
base.Poll();
List<Role> roles = RoleAccountProvider.Instance.GetRoles();
if (!Credential.IsEmpty(BaseApp.Instance.UserContext.Credential))
2023-03-03 15:42:13 +08:00
{
2024-03-18 17:57:54 +08:00
Role role = roles.Find(x => x.RoleName == BaseApp.Instance.UserContext.Role.RoleName);
2023-03-03 15:42:13 +08:00
LogoutTime = role.LogoutTime;
IsAutoLogout = role.IsAutoLogout;
int intervaltime = GetLastInputTime();
//if (System.DateTime.Now >= ClientApp.Instance.UserContext.LoginTime.AddMinutes(LogoutTime) && IsLogin && IsAutoLogout)
if (intervaltime >= LogoutTime * 60 && IsLogin && IsAutoLogout)
Logoff();
else
{
// keep credential alive
var retKeepAlive = AccountClient.Instance.Service.KeepAlive(BaseApp.Instance.UserContext.Token);
switch (retKeepAlive.State)
{
case CredentialKeepAliveStates.Alive or CredentialKeepAliveStates.NotFound:
{
if (_ctsLoginRequestConfirmDialog is { IsCancellationRequested: false })
_ctsLoginRequestConfirmDialog.Cancel();
if (retKeepAlive.State == CredentialKeepAliveStates.NotFound)
{
Logoff();
Execute.OnUIThread(() => { DialogBox.ShowError("You are kicked by RT."); });
}
break;
}
case CredentialKeepAliveStates.RequestingLogin:
{
// 当前用户在其它地方请求登录
if (_ctsLoginRequestConfirmDialog == null ||
_ctsLoginRequestConfirmDialog.IsCancellationRequested)
{
_ctsLoginRequestConfirmDialog = new CancellationTokenSource();
_prgShowLoginRequestConfirmDialog.Report(retKeepAlive.RequestingCredential);
}
/* Execute.OnUIThread(() =>
{
var dlgConfirm = new LoginRequestConfirmationDialog(retKeepAlive.RequestingCredential);
var retDlg = dlgConfirm.ShowDialog();
if (retDlg == true)
{
AccountClient.Instance.Service.ConfirmLoginRequest(retKeepAlive.RequestingCredential.AccountInfo.LoginName);
Logoff();
// 降级为仅查看模式
IsReadOnlyMode = true;
BaseApp.Instance.UserContext.Role = role;
BaseApp.Instance.UserContext.Credential = Credential.ReadOnlyOne;
}
else
{
AccountClient.Instance.Service.RejectLoginRequest(retKeepAlive.RequestingCredential.AccountInfo.LoginName);
}
});*/
// 等待RT处理凭据否则有可能反复触发请求登录确认窗口.
Thread.Sleep(1000);
break;
}
}
}
2023-03-03 15:42:13 +08:00
}
}
catch (Exception ex)
{
LOG.Error(ex.Message);
}
return true;
}
private void StartTimer()
{
2024-03-18 17:57:54 +08:00
DispatcherTimer myDispatcherTimer =
new DispatcherTimer();
2023-03-03 15:42:13 +08:00
myDispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 1000);
myDispatcherTimer.Tick += new EventHandler(Each_Tick);
myDispatcherTimer.Start();
}
public void Each_Tick(object o, EventArgs sender)
{
2024-03-18 17:57:54 +08:00
NowDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
NotifyOfPropertyChange("NowDateTime");
2023-03-03 15:42:13 +08:00
}
#endregion
#endregion
}
}