using DevComponents.DotNetBar.Controls; using DevComponents.DotNetBar; using System.Windows; using System.Drawing; using System; using System.Threading.Tasks; using System.Timers; using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.CompilerServices; using PdmAlert.Entity; using System.Threading; using System.Net.Http; using PdmAlert.Util; using log4net; using WebSocketSharp; using System.Windows.Controls; namespace PdmAlert { /// /// MainWindow.xaml 的交互逻辑 /// public partial class MainWindow : Window, INotifyPropertyChanged { #region INotifyPropertyChanged public virtual event PropertyChangedEventHandler PropertyChanged; protected virtual void RaisePropertyChanged(string name) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } protected void RaiseAndSetIfChanged(ref T old, T @new, [CallerMemberName] string propertyName = null) { old = @new; if (propertyName != null) { RaisePropertyChanged(propertyName); } } #endregion private static ILog Logger = LogManager.GetLogger("MsgAlert"); // private ClientWebSocket socket; private WebSocket socket; private Task readTask; private System.Timers.Timer heartbeatTimer; private CancellationTokenSource cancelTokenSource; private CancellationToken cancelToken; private ToolSetting setting; private HttpClient client; private volatile bool IsRefreshing = false; private string _messageTitle = "共有 0 条未读消息"; public string messageTitle { get => _messageTitle; set => RaiseAndSetIfChanged(ref _messageTitle, value); } private string _statusMessage = "启动中..."; public string statusMessage { get => _statusMessage; set => RaiseAndSetIfChanged(ref _statusMessage, value); } private string _userInfo = ""; public string userInfo { get => _userInfo; set => RaiseAndSetIfChanged(ref _userInfo, value); } private string _socketStatus = ""; public string socketStatus { get => _socketStatus; set => RaiseAndSetIfChanged(ref _socketStatus, value); } private ObservableCollection _messages; public ObservableCollection messages { get => _messages; set => RaiseAndSetIfChanged(ref _messages, value); } public MainWindow() { cancelTokenSource = new CancellationTokenSource(); cancelToken = cancelTokenSource.Token; setting = ToolSetting.Instance; client = new HttpClient { BaseAddress = new Uri($"http://{setting.Ip}:{setting.Port}/{setting.BaseUrl}/"), Timeout = TimeSpan.FromSeconds(setting.TimeOut), }; client.DefaultRequestHeaders.Add("Client-Access-Token", LoginUser.CurrentUser.username); userInfo = $"用户:{LoginUser.CurrentUser.realName}"; DataContext = this; InitializeComponent(); } private void ShowStatus(string status, string message) { Dispatcher.Invoke(() => { socketStatus = status; statusMessage = message; }); } private void Refresh_Click(object sender, RoutedEventArgs e) { MaskAdorner.ShowMask(mainContent); Task.Run(() => { try { RefreshData(); } catch (Exception ex) { Logger.Error("Request Unread Message Failed.", ex); } finally { MaskAdorner.HideMask(mainContent); } }); } public void RefreshData() { try { IsRefreshing = true; Result> res = client.GetSyncAction>("pdm/annountCement/listSysMsgByUser", new Page { pageNo = 1, pageSize = 100 }); Page pageList = res.HandleResult(); Dispatcher.Invoke(() => { messageTitle = $"共有 {pageList.total} 条未读消息"; this.messages = new ObservableCollection(pageList.records); }); } finally { IsRefreshing = false; } } private void FirstRefreshMsg() { try { Result> res = client.GetSyncAction>("pdm/annountCement/listSysMsgByUser", new Page { pageNo = 1, pageSize = 100 }); Page pageList = res.HandleResult(); messageTitle = $"共有 {pageList.total} 条未读消息"; this.messages = new ObservableCollection(pageList.records); if (pageList.total > 0) { Dispatcher.Invoke(() => { eDesktopAlertColor color = eDesktopAlertColor.Default; eAlertPosition position = eAlertPosition.BottomRight; DesktopAlert.Show($"您有{pageList.total}条未读消息,请检查", "\uf005", eSymbolSet.Awesome, Color.Empty, color, position, 5, DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), AlertClicked); }); } } catch (Exception ex) { Logger.Error("First Request Unread Message Failed.", ex); } } private void SwitchUser_Click(object sender, RoutedEventArgs e) { ((App)Application.Current).SwithUser(); } private void AlertClicked(long alertId) { } private void Window_Loaded(object sender, RoutedEventArgs e) { var screeWidth = SystemParameters.WorkArea.Width; var sHeight = SystemParameters.WorkArea.Height; this.Left = screeWidth - this.Width; this.Top = sHeight - this.Height; FirstRefreshMsg(); ConnectWebSocket(); } private void ConnectWebSocket() { try { socket = new WebSocket($"ws://{setting.Ip}:{setting.Port}/{setting.BaseUrl}/daws/{LoginUser.CurrentUser?.id}"); socket.OnOpen += Socket_OnOpen; socket.OnClose += Socket_OnClose; socket.OnMessage += Socket_OnMessage; socket.OnError += Socket_OnError; socket.Connect(); StartHeartBeat(); /*await ws.ConnectAsync(new Uri($"ws://{setting.Ip}:{setting.Port}/{setting.BaseUrl}/daws/{LoginUser.CurrentUser?.id}"), default); socket = ws; ReadMsg(); StartHeartbeat();*/ } catch (Exception ex) { Logger.Error("Connect Websocket Failed.", ex); ShowStatus("Error", "与服务连接连接失败,尝试重连..."); } } private void Socket_OnError(object sender, ErrorEventArgs e) { Logger.Error("Websocket On Error.", e.Exception); //ResetSocket(); //ConnectWebSocket(); } private void Socket_OnMessage(object sender, MessageEventArgs e) { HandleMsg(e.Data); } private void Socket_OnClose(object sender, CloseEventArgs e) { Logger.Info("Websocket On Close."); StopHeartBeat(); } private void Socket_OnOpen(object sender, EventArgs e) { Logger.Info("Websocket On Open."); ShowStatus("Success", "与服务器连接状态正常"); // StartHeartBeat(); } public void StartHeartBeat() { if (heartbeatTimer == null) { heartbeatTimer = new System.Timers.Timer(30 * 1000); heartbeatTimer.Elapsed += HeartbeatTimer_Elapsed; heartbeatTimer.AutoReset = true; heartbeatTimer.Start(); } } private void HeartbeatTimer_Elapsed(object sender, ElapsedEventArgs e) { if (socket == null || !socket.IsAlive) { Logger.Error($"Websocket HeartBeat Error. Socket is NULL:{socket == null}; IsAlive:{socket.IsAlive}"); ShowStatus("Error", "与服务器通讯中断,正在尝试重连..."); ResetSocket(); ConnectWebSocket(); } else { socket.Send("HeartBeat"); } } public void StopHeartBeat() { } /*private void ReadMsg() { readTask = Task.Run(() => { while (socket.State == WebSocketState.Open && !cancelToken.IsCancellationRequested) { byte[] buffer = new byte[1024]; var task = socket.ReceiveAsync(new ArraySegment(buffer), default); task.Wait(); var res = task.Result; var msg = Encoding.UTF8.GetString(buffer, 0, res.Count); HandleMsg(msg); Thread.Sleep(100); } }, cancelToken); }*/ private void HandleMsg(string msg) { if (string.IsNullOrEmpty(msg) || msg == "heartcheck") { return; } Dispatcher.Invoke(() => { eDesktopAlertColor color = eDesktopAlertColor.Default; eAlertPosition position = eAlertPosition.BottomRight; DesktopAlert.Show(msg, "\uf005", eSymbolSet.Awesome, Color.Empty, color, position, 5, DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), AlertClicked); Refresh_Click(null, null); }); } public void ResetSocket() { if (readTask != null) { cancelTokenSource.Cancel(); readTask = null; } if (socket != null) { using (var _socketServer = socket) { try { _socketServer.Close(); socket = null; /*socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "DoDispose", default).Wait(); socket.Dispose();*/ } catch (Exception ex) { Logger.Error("Websocket Close Error.", ex); } } } } public void DoDispose() { if (heartbeatTimer != null) { heartbeatTimer.Stop(); heartbeatTimer.Dispose(); heartbeatTimer = null; } ResetSocket(); if (client != null) { using (var _client = client) { client = null; } } } private void Hide_Click(object sender, RoutedEventArgs e) { this.Hide(); } private void Window_Deactivated(object sender, EventArgs e) { this.Hide(); } private void ReadAll_Click(object sender, RoutedEventArgs e) { MaskAdorner.ShowMask(mainContent); Task.Run(() => { try { Result res = client.PutSyncAction("pdm/sysAnnouncementSend/readAll"); _ = res.HandleResult(); RefreshData(); } catch (Exception ex) { Logger.Error("Read All Fail.", ex); } finally { MaskAdorner.HideMask(mainContent); } }); } private void SingleRead_Click(object sender, RoutedEventArgs e) { Button button = sender as Button; MsgData msg = button.DataContext as MsgData; if (msg == null) return; MaskAdorner.ShowMask(mainContent); Task.Run(() => { try { Result res = client.PutSyncAction("pdm/sysAnnouncementSend/editByAnntIdAndUserId", new MsgData { anntId = msg.id }); _ = res.HandleResult(); RefreshData(); } catch (Exception ex) { Logger.Error("Read All Fail.", ex); } finally { MaskAdorner.HideMask(mainContent); } }); } } }