chr
2024-08-27 df475857ef6214c184d9ed831a393a1afc73277c
PdmAlert/MainWindow.xaml.cs
@@ -2,27 +2,200 @@
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
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    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<T>(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<MsgData> _messages;
        public ObservableCollection<MsgData> 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 long _RunningAlertId = 0;
        private void Button_Click(object sender, RoutedEventArgs e)
        private void ShowStatus(string status, string message)
        {
            eDesktopAlertColor color = eDesktopAlertColor.Default;
            eAlertPosition position = eAlertPosition.BottomRight;
            DesktopAlert.Show("123", "\uf005", eSymbolSet.Awesome, Color.Empty, color, position, 10, ++_RunningAlertId, AlertClicked);
            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)
        {
@@ -32,9 +205,168 @@
        {
            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<byte>(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)
@@ -42,5 +374,60 @@
            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<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);
                }
            });
        }
    }
}