| | |
| | | using DevComponents.DotNetBar; |
| | | using System.Windows; |
| | | using System.Drawing; |
| | | using System.Net.WebSockets; |
| | | using System; |
| | | using System.Threading.Tasks; |
| | | using System.Text; |
| | | using System.Diagnostics; |
| | | 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 |
| | | { |
| | |
| | | } |
| | | #endregion |
| | | |
| | | private ClientWebSocket socket; |
| | | private static ILog Logger = LogManager.GetLogger("MsgAlert"); |
| | | |
| | | // private ClientWebSocket socket; |
| | | private WebSocket socket; |
| | | private Task readTask; |
| | | private Task writeTask; |
| | | 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 条未读消息"; |
| | | |
| | |
| | | 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<MsgData> _messages; |
| | | |
| | |
| | | |
| | | 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<Page<MsgData>> res = client.GetSyncAction<Page<MsgData>>("pdm/annountCement/listSysMsgByUser", new Page<object> |
| | | { |
| | | pageNo = 1, |
| | | pageSize = 100 |
| | | }); |
| | | Page<MsgData> pageList = res.HandleResult(); |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | messageTitle = $"共有 {pageList.total} 条未读消息"; |
| | | this.messages = new ObservableCollection<MsgData>(pageList.records); |
| | | }); |
| | | } |
| | | finally |
| | | { |
| | | IsRefreshing = false; |
| | | } |
| | | } |
| | | |
| | | private void FirstRefreshMsg() |
| | | { |
| | | try |
| | | { |
| | | Result<Page<MsgData>> res = client.GetSyncAction<Page<MsgData>>("pdm/annountCement/listSysMsgByUser", new Page<object> |
| | | { |
| | | pageNo = 1, |
| | | pageSize = 100 |
| | | }); |
| | | Page<MsgData> pageList = res.HandleResult(); |
| | | messageTitle = $"共有 {pageList.total} 条未读消息"; |
| | | this.messages = new ObservableCollection<MsgData>(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) |
| | |
| | | { |
| | | var screeWidth = SystemParameters.WorkArea.Width; |
| | | var sHeight = SystemParameters.WorkArea.Height; |
| | | |
| | | this.Left = screeWidth - this.Width; |
| | | this.Top = sHeight - this.Height; |
| | | |
| | | FirstRefreshMsg(); |
| | | ConnectWebSocket(); |
| | | } |
| | | |
| | | private async Task ConnectWebSocket() |
| | | private void ConnectWebSocket() |
| | | { |
| | | try |
| | | { |
| | | ClientWebSocket ws = new ClientWebSocket(); |
| | | await ws.ConnectAsync(new Uri($"ws://localhost:8888/pdm-web/daws/{LoginUser.CurrentUser?.id}"), default); |
| | | 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(); |
| | | StartHeartbeat();*/ |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | await ConnectWebSocket(); |
| | | Logger.Error("Connect Websocket Failed.", ex); |
| | | ShowStatus("Error", "与服务连接连接失败,尝试重连..."); |
| | | } |
| | | } |
| | | |
| | | private void ReadMsg() |
| | | 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) |
| | | while (socket.State == WebSocketState.Open && !cancelToken.IsCancellationRequested) |
| | | { |
| | | byte[] buffer = new byte[1024]; |
| | | var task = socket.ReceiveAsync(new ArraySegment<byte>(buffer), default); |
| | |
| | | var res = task.Result; |
| | | var msg = Encoding.UTF8.GetString(buffer, 0, res.Count); |
| | | HandleMsg(msg); |
| | | Thread.Sleep(100); |
| | | } |
| | | }); |
| | | } |
| | | }, cancelToken); |
| | | }*/ |
| | | |
| | | private void HandleMsg(string msg) |
| | | { |
| | |
| | | { |
| | | return; |
| | | } |
| | | Debug.WriteLine(msg); |
| | | 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); |
| | | }); |
| | | } |
| | | |
| | | private void StartHeartbeat() |
| | | public void ResetSocket() |
| | | { |
| | | 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.State != WebSocketState.Open) |
| | | if (readTask != null) |
| | | { |
| | | DoDispose(); |
| | | ConnectWebSocket().Wait(); |
| | | cancelTokenSource.Cancel(); |
| | | readTask = null; |
| | | } |
| | | else |
| | | if (socket != null) |
| | | { |
| | | byte[] buffer = Encoding.UTF8.GetBytes("test"); |
| | | socket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, default); |
| | | 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); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | heartbeatTimer.Dispose(); |
| | | heartbeatTimer = null; |
| | | } |
| | | if (readTask != null) |
| | | { |
| | | readTask.Dispose(); |
| | | readTask = null; |
| | | } |
| | | if (socket != null) |
| | | { |
| | | try |
| | | { |
| | | socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "DoDispose", default).Wait(); |
| | | socket.Dispose(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | ResetSocket(); |
| | | |
| | | } |
| | | finally |
| | | if (client != null) |
| | | { |
| | | using (var _client = client) |
| | | { |
| | | socket = null; |
| | | client = null; |
| | | } |
| | | } |
| | | } |
| | |
| | | { |
| | | this.Hide(); |
| | | } |
| | | |
| | | private void ReadAll_Click(object sender, RoutedEventArgs e) |
| | | { |
| | | MaskAdorner.ShowMask(mainContent); |
| | | Task.Run(() => |
| | | { |
| | | try |
| | | { |
| | | Result<object> res = client.PutSyncAction<object>("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<object> res = client.PutSyncAction<object>("pdm/sysAnnouncementSend/editByAnntIdAndUserId", new MsgData |
| | | { |
| | | anntId = msg.id |
| | | }); |
| | | _ = res.HandleResult(); |
| | | RefreshData(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Logger.Error("Read All Fail.", ex); |
| | | } |
| | | finally |
| | | { |
| | | MaskAdorner.HideMask(mainContent); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | } |