From 095dd1b03b29b2407913e80d00f5d2f7d8af57bf Mon Sep 17 00:00:00 2001 From: SL <123@123.com> Date: Wed, 20 Sep 2023 17:50:00 +0800 Subject: [PATCH] =?UTF-8?q?MainView=E4=B8=AD=E5=A2=9E=E5=8A=A0=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7=E5=BC=82=E5=9C=B0=E7=99=BB=E5=BD=95=E7=A1=AE=E8=AE=A4?= =?UTF-8?q?=E5=92=8C=E8=B8=A2=E5=87=BA=E9=80=BB=E8=BE=91=E3=80=82=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9EUI=E5=90=AF=E5=8A=A8=E6=97=B6=E8=8E=B7?= =?UTF-8?q?=E5=8F=96PC=E4=BF=A1=E6=81=AF=E7=9A=84=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=8C=E7=94=A8=E4=BA=8E=E5=B0=86UI=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E4=BC=A0=E9=80=92=E7=BB=99RT=E5=B9=B6?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E4=BA=8E=E6=95=B0=E6=8D=AE=E5=BA=93=E4=B8=AD?= =?UTF-8?q?=E3=80=82=20=E7=A7=BB=E9=99=A4=E6=89=80=E6=9C=89ViewModel?= =?UTF-8?q?=E4=B8=AD=E7=9A=84Permission=E5=B1=9E=E6=80=A7=E5=92=8CIsPermis?= =?UTF-8?q?sion=E5=B1=9E=E6=80=A7=E3=80=82=20=E4=BC=98=E5=8C=96WCF?= =?UTF-8?q?=E8=AF=8A=E6=96=AD=E8=BE=93=E5=87=BA=E6=96=87=E4=BB=B6=E5=90=8D?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SicRT/App.config | 3 +- SicRT/Properties/AssemblyInfo.cs | 2 +- SicUI/App.config | 4 +- SicUI/Bootstrapper.cs | 21 +- SicUI/MainView.xaml | 85 ++++--- SicUI/MainViewModel.cs | 231 +++++++++--------- .../Operations/Overviews/OverViewViewModel.cs | 2 + SicUI/Models/PMs/PMAlarmViewModel.cs | 1 - SicUI/Models/PMs/PMCommMonitorViewModel.cs | 8 +- SicUI/Models/PMs/PMHeaterViewModel.cs | 1 - SicUI/Models/PMs/PMOperationViewModel.cs | 4 +- SicUI/Properties/AssemblyInfo.cs | 2 +- 12 files changed, 188 insertions(+), 176 deletions(-) diff --git a/SicRT/App.config b/SicRT/App.config index 106a13d..e1e140d 100644 --- a/SicRT/App.config +++ b/SicRT/App.config @@ -62,10 +62,11 @@ + initializeData="SicRT_WCF_Error.svclog" /> + diff --git a/SicRT/Properties/AssemblyInfo.cs b/SicRT/Properties/AssemblyInfo.cs index a08011b..9ab4b2b 100644 --- a/SicRT/Properties/AssemblyInfo.cs +++ b/SicRT/Properties/AssemblyInfo.cs @@ -51,7 +51,7 @@ using System.Windows; // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 // 方法是按如下所示使用“*”: : -[assembly: AssemblyVersion("1.1.18.47")] +[assembly: AssemblyVersion("2023.09.18.01")] [assembly: AssemblyInformationalVersion("手动通用版(无EFEM)")] diff --git a/SicUI/App.config b/SicUI/App.config index 49b6e28..6661c44 100644 --- a/SicUI/App.config +++ b/SicUI/App.config @@ -4,7 +4,7 @@
- + + initializeData="SicUI_WCF_Error.svclog" /> diff --git a/SicUI/Bootstrapper.cs b/SicUI/Bootstrapper.cs index 5427b10..4ece1af 100644 --- a/SicUI/Bootstrapper.cs +++ b/SicUI/Bootstrapper.cs @@ -9,6 +9,7 @@ using System.Linq; using System.ServiceModel.Configuration; using System.Text.RegularExpressions; using System.Threading; +using System.Threading.Tasks; using System.Windows; using System.Xml.Linq; using Aitex.Core.RT.Log; @@ -140,7 +141,7 @@ namespace SicUI.Client #endregion #endif - + Task tLoadSysInfo; try { @@ -182,6 +183,16 @@ namespace SicUI.Client #endregion + _splashScreen?.SetMessage1("Initialize logging system ..."); + Singleton.Instance.Initialize(); + + BaseApp.Instance = new ClientApp(); + + tLoadSysInfo = Task.Run(() => + { + BaseApp.Instance.LoadSystemInfo(); + }); + _splashScreen?.SetMessage1( $"Connecting to SicRT ({hostEndpoint.Address.Host}), please wait ..."); @@ -208,7 +219,6 @@ namespace SicUI.Client } } - if (!EventClient.Instance.ConnectRT()) { _splashScreen?.Complete(); @@ -227,11 +237,10 @@ namespace SicUI.Client return; } - _splashScreen?.SetMessage1("Initialize logging system ..."); - Singleton.Instance.Initialize(); + BaseApp.Instance.Initialize(); - _splashScreen?.SetMessage1("Initialize sub modules ..."); - BaseApp.Instance = new ClientApp(); + _splashScreen?.SetMessage1("Preparing Environment ..."); + Task.WaitAll(tLoadSysInfo); _splashScreen?.SetMessage1("Loading the window ..."); diff --git a/SicUI/MainView.xaml b/SicUI/MainView.xaml index 0342f87..c523b17 100644 --- a/SicUI/MainView.xaml +++ b/SicUI/MainView.xaml @@ -30,7 +30,33 @@ - + + + + - - - - - - - - - - + + + + @@ -1166,15 +1186,6 @@ - - - diff --git a/SicUI/MainViewModel.cs b/SicUI/MainViewModel.cs index f822d81..d2b6d2a 100644 --- a/SicUI/MainViewModel.cs +++ b/SicUI/MainViewModel.cs @@ -25,9 +25,11 @@ using System.Windows.Input; using System.Windows.Threading; using Sicentury.Core.Collections; using System.Diagnostics; -using System.Net; using System.Threading.Tasks; using Caliburn.Micro.Core; +using MECF.Framework.Common.MECF.Framework.Common.Account.Extends; +using MECF.Framework.UI.Client.ClientBase.Dialog; +using SciChart.Core.Extensions; namespace SicUI.Client { @@ -339,7 +341,6 @@ namespace SicUI.Client private readonly IEventAggregator _eventAggregator; public MainViewModel(IEventAggregator eventAggregator) { - BaseApp.Instance.Initialize(); ((ClientApp)BaseApp.Instance).ViewModelSwitcher = this; _models = new Dictionary(); _eventAggregator = eventAggregator; @@ -408,37 +409,6 @@ namespace SicUI.Client } break; - case EventType.LoginBySameUser_Notify: - if (Guid.TryParse(evt.Description, out var token) && evt.Tag is Credential requestingCred) - { - if (token == BaseApp.Instance.UserContext.Token) - { - Execute.OnUIThread(()=> - { - var ret = DialogBox.ShowDialog( - DialogButton.Yes | DialogButton.No, - DialogType.INFO, - "Some users is requesting to login the system, you will be forced to switch to read-only mode, do you agree?"); - - if (ret == DialogButton.Yes) - { - AccountClient.Instance.Service.ConfirmLoginRequest(requestingCred); - - Logoff(); - - // 降级为仅查看模式 - BaseApp.Instance.UserContext.Credential = Credential.ReadOnlyOne; - IsReadOnlyMode = true; - } - else - { - AccountClient.Instance.Service.RejectLoginRequest(requestingCred); - } - }); - } - } - break; - case EventType.Sound_Notify: break; case EventType.UIMessage_Notify: @@ -464,79 +434,57 @@ namespace SicUI.Client RequestLogin(loginName, password, role); } - private bool _isShowLoginWaiter; - public bool IsShowLoginWaiter - { - get=>_isShowLoginWaiter; - set - { - _isShowLoginWaiter = value; - NotifyOfPropertyChange(); - } - } - - private string _requestLoginIndicatorText; - public string RequestLoginIndicatorText - { - get => _requestLoginIndicatorText; - set - { - _requestLoginIndicatorText = value; - NotifyOfPropertyChange(); - } - } - private Task _loginTask; - private CancellationTokenSource _ctsWaitingTask; - private string _lastLoginUserName = ""; + private LoginRequestWaitDialog _loginWaitDialog = null; - public void CancelRequestLogin() + /// + /// 显示登录确认等待框。 + /// + /// + /// + private Task ShowRequestLoginWaiter(CancellationTokenSource cts) { - if(string.IsNullOrEmpty(_lastLoginUserName) == false) - AccountClient.Instance.Service.CancelLoginRequest(_lastLoginUserName); - } + var ct = cts.Token; - public Task ShowRequestLoginIndicator() - { return Task.Run(() => { - try - { - _ctsWaitingTask = new CancellationTokenSource(); - var token = _ctsWaitingTask.Token; - var endTime = DateTime.Now.AddSeconds(30); + /*bool? waitResult = null;*/ - // 如果超过一定时间没有从RT返回确认信息,则显示登录中的提示 + // 如果超过一定时间没有从RT返回确认信息,则显示登录中的提示 + Thread.Sleep(500); + + if (ct.IsCancellationRequested) + return; + + Execute.OnUIThread(() => + { + _loginWaitDialog = new LoginRequestWaitDialog(); + _loginWaitDialog.ShowDialog(); + }); + + /*while (true) + { Thread.Sleep(500); - if (token.IsCancellationRequested) - return; + // 等待对话框关闭,不关心返回的DialogResult + // 关闭原因: + // 1. 点击Cancel按钮 + // 2. 超时 + // 3. 远端接受或拒绝请求 + if (waitResult.HasValue) + break; - Execute.OnUIThread(() => IsShowLoginWaiter = true); - - while (true) - { - var remained = (endTime - DateTime.Now).TotalSeconds; - if (remained <= 0) - break; - - Execute.OnUIThread(() => - RequestLoginIndicatorText = - $"Waiting for RT to confirm login request, {remained:0.0}s remained"); - Thread.Sleep(100); - if (token.IsCancellationRequested) - break; - } + if (ct.IsCancellationRequested) + break; } - finally + + // 强制关闭等待对话框 + Execute.OnUIThread(() => { - Execute.OnUIThread(() => - { - RequestLoginIndicatorText = "Waiting for RT to confirm login request, 0s remained"; - IsShowLoginWaiter = false; - }); - } - }); + loginWaitDialog?.Close(); + });*/ + + }, ct); } public async void RequestLogin(string loginName, PasswordBox password, Role role) @@ -544,30 +492,45 @@ namespace SicUI.Client if (_loginTask is { Status: TaskStatus.Running }) return; - _lastLoginUserName = loginName; + #region Validate Parameters - var myInfo = new LoginClientInfo(); - myInfo.HostName = Dns.GetHostName(); - myInfo.HostIP = (await Dns.GetHostEntryAsync(myInfo.HostName)).AddressList[0]; + 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; + } + + #endregion // 向RT请求登录 try { - var taskWaiting = ShowRequestLoginIndicator(); - _loginTask = AccountClient.Instance.Service.LoginEx(loginName, password.Password, role.RoleId, myInfo); + 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); - _ctsWaitingTask.Cancel(); - - if (taskWaiting.Status == TaskStatus.RanToCompletion) - { - // 等待超时 - DialogBox.ShowError("Login failed, timeout of waiting login request confirmation."); - AccountClient.Instance.Service.CancelLoginRequest(loginName); - } - else if (_loginTask.Status == TaskStatus.RanToCompletion) + if (_loginTask.Status == TaskStatus.RanToCompletion) { + // 被接受或拒绝登录 + ctsWaitingTask.Cancel(); + _loginWaitDialog?.Close(); + switch (_loginTask.Result.Result) { case LoginRequestResults.Error: @@ -603,7 +566,7 @@ namespace SicUI.Client //Load menu by role //filer menu if necessary... BaseApp.Instance.MenuManager.LoadMenu( - RoleAccountProvider.Instance.GetMenusByRole(role.RoleId)); + RoleAccountProvider.Instance.GetAccessibleMenusByRole(role.RoleId)); IsAutoLogout = role.IsAutoLogout; LogoutTime = role.LogoutTime; @@ -625,6 +588,17 @@ namespace SicUI.Client } } + else if (taskWaiting.Status == TaskStatus.RanToCompletion) + { + // 等待确认超时 + // 注意:该请求在RT的存活时间比UI超时时间长,因此需要显式取消请求,否则下次登录请求需要等CredentialManager超时后才能重新发起 + AccountClient.Instance.Service.CancelLoginRequest(loginName); + } + else + { + // 两个任务均失败,显式调用下列方法强制RT清理凭据。 + AccountClient.Instance.Service.CancelLoginRequest(loginName); + } } catch (InvalidOperationException ex) { @@ -681,10 +655,10 @@ namespace SicUI.Client else { Logoff(); + IsReadOnlyMode = false; } } - public void Logoff() { BaseApp.Instance.UserMode = UserMode.Logoff; @@ -693,10 +667,9 @@ namespace SicUI.Client try { AccountClient.Instance.Service.LogoutEx(BaseApp.Instance.UserContext.Token); - - BaseApp.Instance.UserContext.Clear(); LOG.Info( $"{BaseApp.Instance.UserContext.LoginName} logoff as {BaseApp.Instance.UserContext.Role.RoleName}"); + BaseApp.Instance.UserContext.Clear(); } catch (Exception exp) { @@ -944,13 +917,39 @@ namespace SicUI.Client else { // keep credential alive - var ret = AccountClient.Instance.Service.KeepAlive(BaseApp.Instance.UserContext.Token); - if (ret == CredentialKeepAliveResults.NotFound) + var retKeepAlive = AccountClient.Instance.Service.KeepAlive(BaseApp.Instance.UserContext.Token); + if (retKeepAlive.State == CredentialKeepAliveStates.NotFound) { Logoff(); - Execute.OnUIThread(() => { DialogBox.ShowError("You are kicked by RT."); }); + } + else if (retKeepAlive.State == CredentialKeepAliveStates.RequestingLogin) + { + // 当前用户在其它地方请求登录 + 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); } } } diff --git a/SicUI/Models/Operations/Overviews/OverViewViewModel.cs b/SicUI/Models/Operations/Overviews/OverViewViewModel.cs index 1a07f5a..280cb3d 100644 --- a/SicUI/Models/Operations/Overviews/OverViewViewModel.cs +++ b/SicUI/Models/Operations/Overviews/OverViewViewModel.cs @@ -15,6 +15,8 @@ using Aitex.Core.RT.Event; using System.Dynamic; using Caliburn.Micro.Core; using MECF.Framework.Common.Account; +using MECF.Framework.Common.Account.Permissions; +using MECF.Framework.UI.Core.Accounts; namespace SicUI.Models.Operations.Overviews { diff --git a/SicUI/Models/PMs/PMAlarmViewModel.cs b/SicUI/Models/PMs/PMAlarmViewModel.cs index 8b39e19..030ed0c 100644 --- a/SicUI/Models/PMs/PMAlarmViewModel.cs +++ b/SicUI/Models/PMs/PMAlarmViewModel.cs @@ -9,7 +9,6 @@ namespace SicUI.Models.PMs { public class PMAlarmViewModel : SicModuleUIViewModelBase, ISupportMultipleSystem { - public bool IsPermission { get => this.Permission == 3; } [IgnorePropertyChange] public List AlarmEvents { get; set; } diff --git a/SicUI/Models/PMs/PMCommMonitorViewModel.cs b/SicUI/Models/PMs/PMCommMonitorViewModel.cs index 033fdf0..3fbb4aa 100644 --- a/SicUI/Models/PMs/PMCommMonitorViewModel.cs +++ b/SicUI/Models/PMs/PMCommMonitorViewModel.cs @@ -53,8 +53,8 @@ namespace SicUI.Models.PMs public Visibility TipsVisble => IsConfinementRingUp && !IsOnline ? Visibility.Hidden : Visibility.Visible; - public bool IsPermission { get => this.Permission == 3; } public bool IsActionEnable => IsConfinementRingUp && !IsOnline; + public bool IsActionEnable1 => false; [Subscription("ConfinementRing.RingUpFaceback")] @@ -296,8 +296,6 @@ namespace SicUI.Models.PMs #endregion - - #region TC2 [Subscription("TC2.L1WorkingOPFeedBack")] public float L1WorkingOP2 { get; set; } @@ -493,10 +491,6 @@ namespace SicUI.Models.PMs #endregion - - - - #endregion [Subscription("TempOmron.ActualTemp")] diff --git a/SicUI/Models/PMs/PMHeaterViewModel.cs b/SicUI/Models/PMs/PMHeaterViewModel.cs index e2f1a39..08396df 100644 --- a/SicUI/Models/PMs/PMHeaterViewModel.cs +++ b/SicUI/Models/PMs/PMHeaterViewModel.cs @@ -60,7 +60,6 @@ namespace SicUI.Models.PMs public Visibility TipsVisble => RingUpSensor ? Visibility.Hidden : Visibility.Visible; - public bool IsPermission { get => this.Permission == 3; } public bool IsActionEnable => RingUpSensor && !IsOnline; public bool IsActionEnable1 => false; diff --git a/SicUI/Models/PMs/PMOperationViewModel.cs b/SicUI/Models/PMs/PMOperationViewModel.cs index 0cb9eb1..d15f73f 100644 --- a/SicUI/Models/PMs/PMOperationViewModel.cs +++ b/SicUI/Models/PMs/PMOperationViewModel.cs @@ -1006,8 +1006,6 @@ namespace SicUI.Models.PMs } } - public bool IsPermission { get => this.Permission == 3; } - public string Module => SystemName; @@ -1548,7 +1546,7 @@ namespace SicUI.Models.PMs base.InitPM(); //权限 - string roleID = BaseApp.Instance.UserContext.Role.RoleId; + var roleID = BaseApp.Instance.UserContext.Role.RoleId; reactorStatusEnable = RoleAccountProvider.Instance.GetMenuPermission(roleID, "PM1.Main.ReactorStatus") == 3; reactorServiceEnable = RoleAccountProvider.Instance.GetMenuPermission(roleID, "PM1.Main.ReactorService") == 3; diff --git a/SicUI/Properties/AssemblyInfo.cs b/SicUI/Properties/AssemblyInfo.cs index d8ce575..f98f851 100644 --- a/SicUI/Properties/AssemblyInfo.cs +++ b/SicUI/Properties/AssemblyInfo.cs @@ -54,6 +54,6 @@ using System.Windows; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.1.18.47")] +[assembly: AssemblyVersion("2023.09.18.01")] [assembly: AssemblyInformationalVersion("手动通用版(无EFEM)")]