From 9ee7d3bd9c58a204b1efe38e6be61155bbb15c16 Mon Sep 17 00:00:00 2001 From: chr <chr@chr.com> Date: 星期三, 21 八月 2024 19:16:22 +0800 Subject: [PATCH] Merge branch 'master' of http://10.10.28.13:8080/r/PDM/PdmSwPlugin2 --- PdmAlert/Entity/MsgData.cs | 8 PdmAlert/app.manifest | 79 +++ PdmAlert/MainWindow.xaml.cs | 171 +++++++ PdmAlert/LoginWindow.xaml | 26 + PdmAlert/Util.cs | 452 +++++++++++++++++++ PdmAlert/Encryptor.cs | 63 ++ PdmAlert/App.xaml.cs | 23 PdmAlert/PdmAlert.csproj | 14 PdmAlert/MainWindow.xaml | 182 ++++--- PdmAlert/lib/Newtonsoft.Json.dll | 0 PdmAlert/Icon/iconfont.ttf | 0 PdmAlert/LoginUser.cs | 117 +++++ PdmAlert/.vs/PdmAlert/v17/DocumentLayout.json | 184 ++++++++ PdmAlert/LoginWindow.xaml.cs | 24 PdmAlert/DockApp.cs | 1 15 files changed, 1,231 insertions(+), 113 deletions(-) diff --git a/PdmAlert/.vs/PdmAlert/v17/DocumentLayout.json b/PdmAlert/.vs/PdmAlert/v17/DocumentLayout.json new file mode 100644 index 0000000..fb64986 --- /dev/null +++ b/PdmAlert/.vs/PdmAlert/v17/DocumentLayout.json @@ -0,0 +1,184 @@ +{ + "Version": 1, + "WorkspaceRootPath": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\", + "Documents": [ + { + "AbsoluteMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|c:\\main\\workspace\\visualstudio\\pdmswplugin2\\pdmalert\\loginuser.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|solutionrelative:loginuser.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\loginwindow.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|solutionrelative:loginwindow.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\mainwindow.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|solutionrelative:mainwindow.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\app.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|solutionrelative:app.xaml.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|c:\\main\\workspace\\visualstudio\\pdmswplugin2\\pdmalert\\loginwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}", + "RelativeMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|solutionrelative:loginwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}" + }, + { + "AbsoluteMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\util.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|solutionrelative:util.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}", + "RelativeMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|solutionrelative:mainwindow.xaml||{F11ACC28-31D1-4C80-A34B-F4E09D3D753C}" + }, + { + "AbsoluteMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\entity\\msgdata.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|solutionrelative:entity\\msgdata.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\dockapp.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|solutionrelative:dockapp.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\encryptor.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{FC7FBDE7-D0D2-4E79-A586-501ABC73FE46}|PdmAlert.csproj|solutionrelative:encryptor.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + } + ], + "DocumentGroupContainers": [ + { + "Orientation": 0, + "VerticalTabListWidth": 256, + "DocumentGroups": [ + { + "DockedWidth": 200, + "SelectedChildIndex": 7, + "Children": [ + { + "$type": "Document", + "DocumentIndex": 4, + "Title": "LoginWindow.xaml", + "DocumentMoniker": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\LoginWindow.xaml", + "RelativeDocumentMoniker": "LoginWindow.xaml", + "ToolTip": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\LoginWindow.xaml", + "RelativeToolTip": "LoginWindow.xaml", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|", + "WhenOpened": "2024-08-20T10:32:06.895Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 5, + "Title": "Util.cs", + "DocumentMoniker": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\Util.cs", + "RelativeDocumentMoniker": "Util.cs", + "ToolTip": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\Util.cs", + "RelativeToolTip": "Util.cs", + "ViewState": "AQIAAKgBAAAAAAAAAAAowLMBAAARAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2024-08-20T10:17:23.879Z" + }, + { + "$type": "Document", + "DocumentIndex": 7, + "Title": "MsgData.cs", + "DocumentMoniker": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\Entity\\MsgData.cs", + "RelativeDocumentMoniker": "Entity\\MsgData.cs", + "ToolTip": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\Entity\\MsgData.cs", + "RelativeToolTip": "Entity\\MsgData.cs", + "ViewState": "AQIAAAAAAAAAAAAAAAAAAAgAAAAAAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2024-08-20T09:14:07.015Z" + }, + { + "$type": "Document", + "DocumentIndex": 6, + "Title": "MainWindow.xaml", + "DocumentMoniker": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\MainWindow.xaml", + "RelativeDocumentMoniker": "MainWindow.xaml", + "ToolTip": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\MainWindow.xaml", + "RelativeToolTip": "MainWindow.xaml", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003549|", + "WhenOpened": "2024-08-20T09:08:54.87Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 2, + "Title": "MainWindow.xaml.cs", + "DocumentMoniker": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\MainWindow.xaml.cs", + "RelativeDocumentMoniker": "MainWindow.xaml.cs", + "ToolTip": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\MainWindow.xaml.cs", + "RelativeToolTip": "MainWindow.xaml.cs", + "ViewState": "AQIAAGIAAAAAAAAAAAAnwJEAAAAsAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2024-08-20T09:03:17.694Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 8, + "Title": "DockApp.cs", + "DocumentMoniker": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\DockApp.cs", + "RelativeDocumentMoniker": "DockApp.cs", + "ToolTip": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\DockApp.cs", + "RelativeToolTip": "DockApp.cs", + "ViewState": "AQIAABkAAAAAAAAAAAAkwA4AAAArAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2024-08-20T06:58:33.822Z" + }, + { + "$type": "Document", + "DocumentIndex": 9, + "Title": "Encryptor.cs", + "DocumentMoniker": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\Encryptor.cs", + "RelativeDocumentMoniker": "Encryptor.cs", + "ToolTip": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\Encryptor.cs", + "RelativeToolTip": "Encryptor.cs", + "ViewState": "AQIAACIAAAAAAAAAAAAawBIAAAAuAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2024-08-20T06:23:54.361Z" + }, + { + "$type": "Document", + "DocumentIndex": 0, + "Title": "LoginUser.cs", + "DocumentMoniker": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\LoginUser.cs", + "RelativeDocumentMoniker": "LoginUser.cs", + "ToolTip": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\LoginUser.cs", + "RelativeToolTip": "LoginUser.cs", + "ViewState": "AQIAAEYAAAAAAAAAAAAywFgAAAANAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2024-08-20T03:50:43.52Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 1, + "Title": "LoginWindow.xaml.cs", + "DocumentMoniker": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\LoginWindow.xaml.cs", + "RelativeDocumentMoniker": "LoginWindow.xaml.cs", + "ToolTip": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\LoginWindow.xaml.cs", + "RelativeToolTip": "LoginWindow.xaml.cs", + "ViewState": "AQIAAAYAAAAAAAAAAAAAABAAAAAfAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2024-08-20T03:46:25.163Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 3, + "Title": "App.xaml.cs", + "DocumentMoniker": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\App.xaml.cs", + "RelativeDocumentMoniker": "App.xaml.cs", + "ToolTip": "C:\\Main\\Workspace\\VisualStudio\\PdmSwPlugin2\\PdmAlert\\App.xaml.cs", + "RelativeToolTip": "App.xaml.cs", + "ViewState": "AQIAAAgAAAAAAAAAAAAIwBgAAAAjAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2024-08-20T03:42:24.667Z", + "EditorCaption": "" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/PdmAlert/App.xaml.cs b/PdmAlert/App.xaml.cs index 67e9db4..9740dfb 100644 --- a/PdmAlert/App.xaml.cs +++ b/PdmAlert/App.xaml.cs @@ -1,10 +1,4 @@ -锘縰sing System; -using System.Collections.Generic; -using System.Configuration; -using System.Data; -using System.Linq; -using System.Threading.Tasks; -using System.Windows; +锘縰sing System.Windows; namespace PdmAlert { @@ -14,16 +8,27 @@ public partial class App : Application { DockApp dockApp; + LoginWindow loginWindow; protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); this.ShutdownMode = ShutdownMode.OnExplicitShutdown; - dockApp.Run(); + if (LoginUser.TryAutoLogin()) + { + + dockApp = new DockApp(); + dockApp.Run(); + } + else + { + loginWindow = new LoginWindow(); + loginWindow.Show(); + } } private void Application_Startup(object sender, StartupEventArgs e) { - dockApp = new DockApp(); + } } } diff --git a/PdmAlert/DockApp.cs b/PdmAlert/DockApp.cs index b68feff..4e78dbc 100644 --- a/PdmAlert/DockApp.cs +++ b/PdmAlert/DockApp.cs @@ -38,6 +38,7 @@ if (showWindow != null) { showWindow.Show(); + showWindow.Activate(); } else { diff --git a/PdmAlert/Encryptor.cs b/PdmAlert/Encryptor.cs new file mode 100644 index 0000000..88768ab --- /dev/null +++ b/PdmAlert/Encryptor.cs @@ -0,0 +1,63 @@ +锘縰sing System; +using System.IO; +using System.Security.Cryptography; +using System.Text; + +namespace PdmAlert +{ + public class Encryptor + { + private readonly byte[] key; + private readonly byte[] iv; + + public Encryptor(string keyString, string ivString) + { + key = Encoding.UTF8.GetBytes(keyString); + iv = Encoding.UTF8.GetBytes(ivString); + } + + public string Encrypt(string plainText) + { + using (var aes = Aes.Create()) + { + aes.Key = key; + aes.IV = iv; + ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); + + using (MemoryStream msEncrypt = new MemoryStream()) + { + using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) + { + using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) + { + swEncrypt.Write(plainText); + } + return Convert.ToBase64String(msEncrypt.ToArray()); + } + } + } + } + + + public string Decrypt(string cipherText) + { + using (var aes = Aes.Create()) + { + aes.Key = key; + aes.IV = iv; + ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); + byte[] arr = Convert.FromBase64String(cipherText); + using (MemoryStream msDecrypt = new MemoryStream(arr)) + { + using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) + { + using (StreamReader srDecrypt = new StreamReader(csDecrypt)) + { + return srDecrypt.ReadToEnd(); + } + } + } + } + } + } +} diff --git a/PdmAlert/Entity/MsgData.cs b/PdmAlert/Entity/MsgData.cs new file mode 100644 index 0000000..c428e94 --- /dev/null +++ b/PdmAlert/Entity/MsgData.cs @@ -0,0 +1,8 @@ +锘縩amespace PdmAlert.Entity +{ + public class MsgData + { + public string title { get; set; } + public string content { get; set; } + } +} diff --git a/PdmAlert/Icon/iconfont.ttf b/PdmAlert/Icon/iconfont.ttf new file mode 100644 index 0000000..66fd530 --- /dev/null +++ b/PdmAlert/Icon/iconfont.ttf Binary files differ diff --git a/PdmAlert/LoginUser.cs b/PdmAlert/LoginUser.cs new file mode 100644 index 0000000..f397804 --- /dev/null +++ b/PdmAlert/LoginUser.cs @@ -0,0 +1,117 @@ +锘縰sing PdmAlert.Util; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Http; +using System.Reflection; + +namespace PdmAlert +{ + public class LoginUser + { + public static LoginUser CurrentUser { get; private set; } + + private static readonly Encryptor encryptor = new Encryptor("12345678123456781234567812345678", + "1234567812345678"); + + public string id { get; set; } + public string realName { get; set; } + public string username { get; set; } + public string password { get; set; } + public string appId { get; set; } + public string pluginVersion { get; set; } + public bool rememberMe { get; set; } + + public static bool TryAutoLogin() + { + string fileContent = null; + if (LoadStrFromBin(ref fileContent)) + { + try + { + string jsonStr = encryptor.Decrypt(fileContent); + Dictionary<string, string> user = JsonUtil.Deserialize<Dictionary<string, string>>(jsonStr); + return Login(user["username"], user["password"], true); + } + catch (Exception ex) + { + RemoveCacheBin(); + return false; + } + + } + return false; + } + + public static bool Login(string username, string password, bool rememberMe) + { + + using (HttpClient client = new HttpClient + { + BaseAddress = new Uri("http://localhost:8888/pdm-web/"), + }) + { + try + { + Result<LoginUser> res = client.PostSyncAction<LoginUser>(new LoginUser + { + username = username, + password = password, + appId = "sockettool", + pluginVersion = "0.0.0.1" + + }, "openApi/wpf/login"); + CurrentUser = res.HandleResult(); + CurrentUser.password = password; + CurrentUser.rememberMe = rememberMe; + if (rememberMe) + { + string userInfo = JsonUtil.Stringfiy(CurrentUser); + SaveStrToBin(encryptor.Encrypt(userInfo)); + } + return true; + } + catch (Exception ex) + { + RemoveCacheBin(); + } + } + return false; + } + + + public static void SaveStrToBin(string content) + { + string filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().FullName), "bin"); + byte[] bytes = Convert.FromBase64String(content); + using (Stream stream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite)) + using (BinaryWriter writer = new BinaryWriter(stream)) + { + writer.Write(bytes); + } + } + + public static bool LoadStrFromBin(ref string content) + { + string filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().FullName), "bin"); + if (!File.Exists(filePath)) + { + return false; + } + using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) + using (BinaryReader reader = new BinaryReader(stream)) + { + byte[] bytes = new byte[stream.Length]; + reader.Read(bytes, 0, bytes.Length); + content = Convert.ToBase64String(bytes); + return true; + } + } + + public static void RemoveCacheBin() + { + string filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().FullName), "bin"); + File.Delete(filePath); + } + } +} diff --git a/PdmAlert/LoginWindow.xaml b/PdmAlert/LoginWindow.xaml index 73fe38e..d6f4081 100644 --- a/PdmAlert/LoginWindow.xaml +++ b/PdmAlert/LoginWindow.xaml @@ -6,7 +6,27 @@ xmlns:local="clr-namespace:PdmAlert" mc:Ignorable="d" Title="LoginWindow" Height="450" Width="800"> - <Grid> - - </Grid> + <AdornerDecorator> + <Border x:Name="mainBorder"> + <Grid Height="200" VerticalAlignment="Top" Margin="20"> + <Grid.RowDefinitions> + <RowDefinition Height="30"/> + <RowDefinition Height="30"/> + <RowDefinition Height="30"/> + <RowDefinition Height="50"/> + </Grid.RowDefinitions> + + <Grid.ColumnDefinitions> + <ColumnDefinition Width="50"/> + <ColumnDefinition/> + </Grid.ColumnDefinitions> + <Label Content="鐢ㄦ埛鍚�" VerticalContentAlignment="Center" Grid.Row="0" Grid.Column="0"/> + <TextBox x:Name="usernameTextBlock" VerticalAlignment="Stretch" VerticalContentAlignment="Center" Grid.Row="0" Grid.Column="1"/> + <Label Content="瀵嗙爜" VerticalContentAlignment="Center" Grid.Row="1" Grid.Column="0"/> + <PasswordBox x:Name="passwordTextBlock" VerticalAlignment="Stretch" VerticalContentAlignment="Center" Grid.Row="1" Grid.Column="1"/> + <CheckBox Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" x:Name="rememberMeInput">鑷姩鐧诲綍</CheckBox> + <Button Margin="0,10,0,0" Click="Button_Click" Padding="5" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2">鐧诲綍</Button> + </Grid> + </Border> + </AdornerDecorator> </Window> diff --git a/PdmAlert/LoginWindow.xaml.cs b/PdmAlert/LoginWindow.xaml.cs index 99cd421..6db9861 100644 --- a/PdmAlert/LoginWindow.xaml.cs +++ b/PdmAlert/LoginWindow.xaml.cs @@ -1,16 +1,4 @@ -锘縰sing System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; +锘縰sing System.Windows; namespace PdmAlert { @@ -23,5 +11,15 @@ { InitializeComponent(); } + + public void Button_Click(object sender, RoutedEventArgs e) + { + if (LoginUser.Login(usernameTextBlock.Text, passwordTextBlock.Password, rememberMeInput.IsChecked == true)) + { + + + } + + } } } diff --git a/PdmAlert/MainWindow.xaml b/PdmAlert/MainWindow.xaml index 1f51b53..3defeb9 100644 --- a/PdmAlert/MainWindow.xaml +++ b/PdmAlert/MainWindow.xaml @@ -6,115 +6,135 @@ xmlns:local="clr-namespace:PdmAlert" mc:Ignorable="d" WindowStyle="None" + Topmost="True" ResizeMode="NoResize" WindowStartupLocation="Manual" Loaded="Window_Loaded" + Deactivated="Window_Deactivated" + ShowInTaskbar="False" Title="MainWindow" Height="600" Width="400"> <Window.Resources> - <Brush x:Key="MainBorder">#0d4d84</Brush> - <Brush x:Key="MainMenu">#1d6eb2</Brush> - <Brush x:Key="ChildBorder">#3692e1</Brush> - <Brush x:Key="MainStatusBar">#1d6eb2</Brush> + <ResourceDictionary> + <FontFamily x:Key="iconfont"> + /PdmAlert;component/Icon/#iconfont + </FontFamily> + <Brush x:Key="MainBorder">#0d4d84</Brush> + <Brush x:Key="MainMenu">#1d6eb2</Brush> + <Brush x:Key="ChildBorder">#3692e1</Brush> + <Brush x:Key="MainStatusBar">#1d6eb2</Brush> - <Brush x:Key="SecondaryImportant">Orange</Brush> - <Brush x:Key="Important">#e17933</Brush> - <Brush x:Key="ImportantFont">#FFF</Brush> + <Brush x:Key="SecondaryImportant">Orange</Brush> + <Brush x:Key="Important">#e17933</Brush> + <Brush x:Key="ImportantFont">#FFF</Brush> - <Brush x:Key="ButtonColor">#103156</Brush> - <Brush x:Key="ButtonSelected">#02579E</Brush> - <Brush x:Key="ButtonFont">White</Brush> - <Brush x:Key="ButtonFontSelected">White</Brush> - - <Style x:Key="WindowButton" TargetType="Button"> - <Setter Property="Background" Value="Transparent"/> - <Setter Property="FontWeight" Value="SemiBold"/> - <Setter Property="Foreground" Value="White"/> - <Setter Property="Width" Value="50"/> - <Setter Property="FontSize" Value="20"/> - <Setter Property="BorderThickness" Value="0"/> - <Setter Property="BorderBrush" Value="Transparent"/> + <Brush x:Key="ButtonColor">#103156</Brush> + <Brush x:Key="ButtonSelected">#02579E</Brush> + <Brush x:Key="ButtonFont">White</Brush> + <Brush x:Key="ButtonFontSelected">White</Brush> + + <Style x:Key="WindowButton" TargetType="Button"> + <Setter Property="FontFamily" Value="{StaticResource iconfont}"/> + <Setter Property="Background" Value="Transparent"/> + <Setter Property="FontWeight" Value="SemiBold"/> + <Setter Property="Foreground" Value="Black"/> + <Setter Property="Width" Value="50"/> + <Setter Property="FontSize" Value="20"/> + <Setter Property="BorderThickness" Value="1"/> + <Setter Property="BorderBrush" Value="Transparent"/> - <Setter Property="Template"> - <Setter.Value> - <ControlTemplate TargetType="Button"> - <Border x:Name="border" Width="{TemplateBinding Width}" Background="{TemplateBinding Background}" + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="Button"> + <Border x:Name="border" Width="{TemplateBinding Width}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0"> - <Label x:Name="label" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" + <Label x:Name="label" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Foreground="{TemplateBinding Foreground}" Content="{TemplateBinding Content}"/> - </Border> + </Border> - <ControlTemplate.Triggers> - <Trigger Property="IsMouseOver" Value="True"> - <Setter TargetName="border" Property="Background" Value="Gray"/> - </Trigger> - </ControlTemplate.Triggers> - </ControlTemplate> - </Setter.Value> - </Setter> - </Style> + <ControlTemplate.Triggers> + <Trigger Property="IsMouseOver" Value="True"> + <Setter TargetName="border" Property="Background" Value="Gray"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> - <Style x:Key="WindowCloseButton" BasedOn="{StaticResource WindowButton}" TargetType="Button"> - <Setter Property="Template"> - <Setter.Value> - <ControlTemplate TargetType="Button"> - <Border x:Name="border" Width="{TemplateBinding Width}" Background="{TemplateBinding Background}" + <Style x:Key="WindowCloseButton" BasedOn="{StaticResource WindowButton}" TargetType="Button"> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="Button"> + <Border x:Name="border" Width="{TemplateBinding Width}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0"> - <Label x:Name="label" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" + <Label x:Name="label" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Foreground="{TemplateBinding Foreground}" Content="{TemplateBinding Content}"/> - </Border> + </Border> - <ControlTemplate.Triggers> - <Trigger Property="IsMouseOver" Value="True"> - <Setter TargetName="border" Property="Background" Value="Red"/> - </Trigger> - </ControlTemplate.Triggers> - </ControlTemplate> - </Setter.Value> - </Setter> - </Style> + <ControlTemplate.Triggers> + <Trigger Property="IsMouseOver" Value="True"> + <Setter TargetName="border" Property="Background" Value="Red"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> - <Style x:Key="ChildWindowButton" BasedOn="{StaticResource WindowButton}" TargetType="Button"> - <Setter Property="FontSize" Value="15"/> - <Setter Property="Width" Value="30"/> - <Setter Property="Background" Value="{StaticResource ChildBorder}"/> - </Style> + <Style x:Key="ChildWindowButton" BasedOn="{StaticResource WindowButton}" TargetType="Button"> + <Setter Property="FontSize" Value="15"/> + <Setter Property="Width" Value="30"/> + <Setter Property="Background" Value="{StaticResource ChildBorder}"/> + </Style> - <Style x:Key="ChildWindowCloseButton" BasedOn="{StaticResource ChildWindowButton}" TargetType="Button"> - - </Style> + <Style x:Key="ChildWindowCloseButton" BasedOn="{StaticResource ChildWindowButton}" TargetType="Button"> - <Style x:Key="LinkButton" TargetType="Button"> - <Setter Property="FontFamily" Value="{StaticResource iconfont}"/> - <Setter Property="Foreground" Value="{StaticResource ChildBorder}"/> + </Style> - <Setter Property="Template"> - <Setter.Value> - <ControlTemplate TargetType="Button"> - <TextBlock Style="{x:Null}" x:Name="label" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" + <Style x:Key="LinkButton" TargetType="Button"> + <Setter Property="FontFamily" Value="{StaticResource iconfont}"/> + <Setter Property="Foreground" Value="{StaticResource ChildBorder}"/> + + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="Button"> + <TextBlock Style="{x:Null}" x:Name="label" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Foreground="{TemplateBinding Foreground}" Text="{TemplateBinding Content}"/> - </ControlTemplate> - </Setter.Value> - </Setter> - </Style> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + </ResourceDictionary> </Window.Resources> - - + + <StackPanel> - <StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right"> - <Button Style="{StaticResource WindowButton}" Click="Button_Click">鍒锋柊</Button> - <Button Style="{StaticResource WindowButton}" Click="Button_Click">鍒囨崲鐢ㄦ埛</Button> - <Button Style="{StaticResource WindowCloseButton}" Click="Hide_Click">鏈�灏忓寲</Button> - </StackPanel> - <Grid> - <Button Click="Button_Click">娴嬭瘯</Button> - </Grid> + <Border BorderThickness="0" Background="LightGray"> + <StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right"> + <Button Style="{StaticResource WindowButton}" Click="Refresh_Click" BorderBrush="Black" ToolTip="鍒锋柊"></Button> + <Button Style="{StaticResource WindowButton}" Click="SwitchUser_Click" ToolTip="鍒囨崲鐢ㄦ埛"></Button> + <Button Style="{StaticResource WindowCloseButton}" Click="Hide_Click" ToolTip="鏈�灏忓寲"></Button> + </StackPanel> + </Border> + + + <Label Content="{Binding messageTitle}"/> + + <ListView ItemsSource="{Binding messages}"> + <ListView.ItemTemplate> + <DataTemplate> + <Label Content="999"/> + </DataTemplate> + </ListView.ItemTemplate> + </ListView> + </StackPanel> - + </Window> diff --git a/PdmAlert/MainWindow.xaml.cs b/PdmAlert/MainWindow.xaml.cs index 1f2fcde..8d0f0e9 100644 --- a/PdmAlert/MainWindow.xaml.cs +++ b/PdmAlert/MainWindow.xaml.cs @@ -2,27 +2,80 @@ 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; 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 ClientWebSocket socket; + private Task readTask; + private Task writeTask; + private System.Timers.Timer heartbeatTimer; + + private string _messageTitle = "鍏辨湁 0 鏉℃湭璇绘秷鎭�"; + + public string messageTitle + { + get => _messageTitle; + set => RaiseAndSetIfChanged(ref _messageTitle, value); + } + + private ObservableCollection<MsgData> _messages; + + public ObservableCollection<MsgData> messages + { + get => _messages; + set => RaiseAndSetIfChanged(ref _messages, value); + } + public MainWindow() { InitializeComponent(); } - private long _RunningAlertId = 0; - private void Button_Click(object sender, RoutedEventArgs e) + private void Refresh_Click(object sender, RoutedEventArgs e) { - eDesktopAlertColor color = eDesktopAlertColor.Default; - eAlertPosition position = eAlertPosition.BottomRight; - DesktopAlert.Show("123", "\uf005", eSymbolSet.Awesome, Color.Empty, color, position, 10, ++_RunningAlertId, AlertClicked); + } + + private void SwitchUser_Click(object sender, RoutedEventArgs e) + { + + + } + private void AlertClicked(long alertId) { @@ -35,6 +88,108 @@ this.Left = screeWidth - this.Width; this.Top = sHeight - this.Height; + ConnectWebSocket(); + } + + private async Task ConnectWebSocket() + { + try + { + ClientWebSocket ws = new ClientWebSocket(); + await ws.ConnectAsync(new Uri($"ws://localhost:8888/pdm-web/daws/{LoginUser.CurrentUser?.id}"), default); + socket = ws; + ReadMsg(); + StartHeartbeat(); + } + catch (Exception ex) + { + await ConnectWebSocket(); + } + } + + private void ReadMsg() + { + readTask = Task.Run(() => + { + while (socket.State == WebSocketState.Open) + { + 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); + } + }); + } + + private void HandleMsg(string msg) + { + if (string.IsNullOrEmpty(msg) || msg == "heartcheck") + { + 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); + }); + } + + private void StartHeartbeat() + { + 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) + { + DoDispose(); + ConnectWebSocket().Wait(); + } + else + { + byte[] buffer = Encoding.UTF8.GetBytes("test"); + socket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, default); + } + } + + public void DoDispose() + { + if (heartbeatTimer != null) + { + heartbeatTimer.Stop(); + 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) + { + + } + finally + { + socket = null; + } + } } private void Hide_Click(object sender, RoutedEventArgs e) @@ -42,5 +197,9 @@ this.Hide(); } + private void Window_Deactivated(object sender, EventArgs e) + { + this.Hide(); + } } } diff --git a/PdmAlert/PdmAlert.csproj b/PdmAlert/PdmAlert.csproj index 74f7194..9a18d0d 100644 --- a/PdmAlert/PdmAlert.csproj +++ b/PdmAlert/PdmAlert.csproj @@ -54,13 +54,20 @@ <ErrorReport>prompt</ErrorReport> <Prefer32Bit>true</Prefer32Bit> </PropertyGroup> + <PropertyGroup> + <ApplicationManifest>app.manifest</ApplicationManifest> + </PropertyGroup> <ItemGroup> <Reference Include="DevComponents.DotNetBar2"> <HintPath>..\lib\DevComponents.DotNetBar2.dll</HintPath> </Reference> + <Reference Include="Newtonsoft.Json"> + <HintPath>lib\Newtonsoft.Json.dll</HintPath> + </Reference> <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.Drawing" /> + <Reference Include="System.Web" /> <Reference Include="System.Windows.Forms" /> <Reference Include="System.Xml" /> <Reference Include="Microsoft.CSharp" /> @@ -80,6 +87,7 @@ <Generator>MSBuild:Compile</Generator> <SubType>Designer</SubType> </ApplicationDefinition> + <Compile Include="Util.cs" /> <Page Include="LoginWindow.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> @@ -93,6 +101,9 @@ <SubType>Code</SubType> </Compile> <Compile Include="DockApp.cs" /> + <Compile Include="Encryptor.cs" /> + <Compile Include="Entity\MsgData.cs" /> + <Compile Include="LoginUser.cs" /> <Compile Include="LoginWindow.xaml.cs"> <DependentUpon>LoginWindow.xaml</DependentUpon> </Compile> @@ -119,6 +130,8 @@ <Generator>ResXFileCodeGenerator</Generator> <LastGenOutput>Resources.Designer.cs</LastGenOutput> </EmbeddedResource> + <None Include="app.manifest" /> + <Resource Include="Icon\iconfont.ttf" /> <None Include="Properties\Settings.settings"> <Generator>SettingsSingleFileGenerator</Generator> <LastGenOutput>Settings.Designer.cs</LastGenOutput> @@ -127,7 +140,6 @@ <ItemGroup> <None Include="App.config" /> </ItemGroup> - <ItemGroup /> <ItemGroup> <Content Include="Icon\Icon.ico"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> diff --git a/PdmAlert/Util.cs b/PdmAlert/Util.cs new file mode 100644 index 0000000..b5ed241 --- /dev/null +++ b/PdmAlert/Util.cs @@ -0,0 +1,452 @@ +锘縰sing System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using System.Web; +using Newtonsoft.Json; + +namespace PdmAlert.Util +{ + [Serializable] + public class Result<T> + { + [JsonProperty("success")] + public bool success + { + get; set; + } + + [JsonProperty("message")] + public string message + { + get; set; + } + + [JsonProperty("code")] + public int code + { + get; set; + } + + [JsonProperty("result")] + public T result + { + get; set; + } + } + + public static class ResultHandler + { + public static T HandleResult<T>(this Result<T> result) + { + if (result.success) + { + return result.result; + } + throw new CustomWebException(result.message); + } + } + + /// <summary> + /// 鑷畾涔変粠Web杩斿洖鐨勫紓甯� + /// </summary> + public class CustomWebException : Exception + { + public CustomWebException() + { + + } + + public CustomWebException(string message) : base(message) + { + + } + + public CustomWebException(string message, Exception inner) : base(message, inner) + { + + } + } + + public class JsonUtil + { + static readonly JsonSerializerSettings JsSetting = new JsonSerializerSettings() + { + NullValueHandling = NullValueHandling.Ignore + }; + + public static T Deserialize<T>(string jsonStr) + { + return JsonConvert.DeserializeObject<T>(jsonStr); + } + + public static string Serialize(object obj) + { + return JsonConvert.SerializeObject(obj); + } + + public static string Stringfiy(object obj) + { + return JsonConvert.SerializeObject(obj, Formatting.Indented, JsSetting); + } + + } + + public static class HttpUtil + { + + /// <summary> + /// Http GET 鍚屾鑾峰彇瀵硅薄 + /// </summary> + /// <typeparam name="T">瀵硅薄绫诲瀷</typeparam> + /// <param name="client">瀹㈡埛绔�</param> + /// <param name="url">url</param> + /// <param name="models">鍙傛暟</param> + /// <returns>Http杩斿洖缁撴灉</returns> + public static Result<T> GetSyncAction<T>(this HttpClient client, string url, params object[] models) + { + return JsonUtil.Deserialize<Result<T>>(GetSyncAction(client, url, models)); + } + + /// <summary> + /// Http GET 鍚屾鑾峰彇瀛楃 + /// </summary> + /// <param name="client">瀹㈡埛绔�</param> + /// <param name="url">url</param> + /// <param name="models">鍙傛暟</param> + /// <returns>Http杩斿洖缁撴灉</returns> + public static string GetSyncAction(this HttpClient client, string url, params object[] models) + { + try + { + foreach (object model in models) + { + url = url.ModelToUriParam(model); + } + + Task<string> task = client.GetStringAsync(url); + task.Wait(); + return task.Result; + } + catch (Exception e) + { + throw new CustomWebException("璇锋眰寮傚父", e); + } + } + + /// <summary> + /// Http GET 寮傛鑾峰彇瀵硅薄 + /// </summary> + /// <typeparam name="T">瀵硅薄绫诲瀷</typeparam> + /// <param name="client">瀹㈡埛绔�</param> + /// <param name="url">url</param> + /// <param name="models">鍙傛暟</param> + /// <returns>寮傛Http杩斿洖缁撴灉</returns> + public static async Task<Result<T>> GetAsyncAction<T>(this HttpClient client, string url, params object[] models) + { + try + { + foreach (object model in models) + { + url = url.ModelToUriParam(model); + } + return JsonUtil.Deserialize<Result<T>>(await client.GetStringAsync(url)); + } + catch (Exception e) + { + throw new CustomWebException("璇锋眰寮傚父", e); + } + } + + /// <summary> + /// Http POST 鍚屾鑾峰彇瀵硅薄 + /// </summary> + /// <typeparam name="T">瀵硅薄绫诲瀷</typeparam> + /// <param name="client">瀹㈡埛绔�</param> + /// <param name="url">url</param> + /// <param name="data">鍙傛暟json瀛楃</param> + /// <returns>Http杩斿洖缁撴灉</returns> + public static Result<T> PostSyncAction<T>(this HttpClient client, string url, string data) + { + StringContent content = new StringContent(data, Encoding.UTF8, "application/json"); + Task<HttpResponseMessage> task = client.PostAsync(url, content); + task.Wait(); + HttpResponseMessage response = task.Result; + response.EnsureSuccessStatusCode(); + Task<string> task2 = response.Content.ReadAsStringAsync(); + task2.Wait(); + string responseBody = task2.Result; + return JsonUtil.Deserialize<Result<T>>(responseBody); + } + + /// <summary> + /// Http POST 鍚屾鑾峰彇瀵硅薄 + /// </summary> + /// <typeparam name="T">瀵硅薄绫诲瀷</typeparam> + /// <param name="client">瀹㈡埛绔�</param> + /// <param name="url">url</param> + /// <param name="content">Http璐熻浇</param> + /// <returns>Http杩斿洖缁撴灉</returns> + public static Result<T> PostSyncAction<T>(this HttpClient client, string url, HttpContent content) + { + Task<HttpResponseMessage> task = client.PostAsync(url, content); + task.Wait(); + HttpResponseMessage response = task.Result; + response.EnsureSuccessStatusCode(); + Task<string> task2 = response.Content.ReadAsStringAsync(); + task2.Wait(); + return JsonUtil.Deserialize<Result<T>>(task2.Result); + } + + /// <summary> + /// Http POST 鍚屾鑾峰彇瀵硅薄 + /// </summary> + /// <typeparam name="T">瀵硅薄绫诲瀷</typeparam> + /// <param name="client">瀹㈡埛绔�</param> + /// <param name="data">鍙傛暟瀵硅薄</param> + /// <param name="url">url</param> + /// <returns>Http杩斿洖缁撴灉</returns> + public static Result<T> PostSyncAction<T>(this HttpClient client, object data, string url) + { + string dataStr = JsonUtil.Serialize(data); + StringContent content = new StringContent(dataStr, Encoding.UTF8, "application/json"); + Task<HttpResponseMessage> task = client.PostAsync(url, content); + task.Wait(); + HttpResponseMessage response = task.Result; + response.EnsureSuccessStatusCode(); + Task<string> task2 = response.Content.ReadAsStringAsync(); + task2.Wait(); + string responseBody = task2.Result; + return JsonUtil.Deserialize<Result<T>>(responseBody); + } + + public static string PostSyncAction(this HttpClient client, string url, string data) + { + StringContent content = new StringContent(data, Encoding.UTF8, "application/json"); + Task<HttpResponseMessage> task = client.PostAsync(url, content); + task.Wait(); + HttpResponseMessage response = task.Result; + response.EnsureSuccessStatusCode(); + Task<string> task2 = response.Content.ReadAsStringAsync(); + task2.Wait(); + return task2.Result; + } + + public static async Task<T> PostAsyncAction<T>(this HttpClient client, string url, string data) + { + StringContent content = new StringContent(data, Encoding.UTF8, "application/json"); + HttpResponseMessage response = await client.PostAsync(url, content); + _ = response.EnsureSuccessStatusCode(); + return JsonUtil.Deserialize<T>(await response.Content.ReadAsStringAsync()); + } + + public static async Task<Result<T>> PostAsyncAction<T>(this HttpClient client, string url, object data) + { + string dataStr = JsonUtil.Serialize(data); + StringContent content = new StringContent(dataStr, Encoding.UTF8, "application/json"); + HttpResponseMessage response = await client.PostAsync(url, content); + _ = response.EnsureSuccessStatusCode(); + return JsonUtil.Deserialize<Result<T>>(await response.Content.ReadAsStringAsync()); + } + + public static async Task<Result<T>> PostAsyncAction<T>(this HttpClient client, string url, HttpContent content) + { + HttpResponseMessage response = await client.PostAsync(url, content); + _ = response.EnsureSuccessStatusCode(); + return JsonUtil.Deserialize<Result<T>>(await response.Content.ReadAsStringAsync()); + } + + /// <summary> + /// 涓嬭浇鏂囦欢淇濆瓨鍒扮粷瀵硅矾寰� + /// </summary> + /// <param name="client"></param> + /// <param name="url"></param> + /// <param name="absolutePath"></param> + /// <param name="models"></param> + public static async Task GetDownload(this HttpClient client, string url, string absolutePath, params object[] models) + { + foreach (object model in models) + { + url = url.ModelToUriParam(model); + } + HttpResponseMessage response = await client.GetAsync(url); + int code = Convert.ToInt32(response.StatusCode); + if (code == 200) + { + using (Stream stream = await response.Content.ReadAsStreamAsync()) + { + string suffix = Path.GetExtension(response.RequestMessage.RequestUri.ToString()); + using (FileStream fs = new FileStream(absolutePath, FileMode.OpenOrCreate)) + { + byte[] buffer = new byte[1024]; + int readLength = 0; + int length; + while ((length = await stream.ReadAsync(buffer, 0, buffer.Length)) != 0) + { + readLength += length; + fs.Write(buffer, 0, length); + } + } + } + } + else + { + string error = "鍥剧焊涓嬭浇澶辫触"; + if (response.Headers.TryGetValues("FileName", out IEnumerable<string> values)) + { + error = values.First(); + } + throw new CustomWebException(error); + } + } + + /// <summary> + /// 涓嬭浇鏂囦欢淇濆瓨鍒扮粷瀵硅矾寰� + /// </summary> + /// <param name="client"></param> + /// <param name="url"></param> + /// <param name="absolutePath"></param> + /// <param name="models"></param> + public static void GetDownloadSync(this HttpClient client, string url, string absolutePath, params object[] models) + { + foreach (object model in models) + { + url = url.ModelToUriParam(model); + } + Task<HttpResponseMessage> task = client.GetAsync(url); + task.Wait(); + HttpResponseMessage response = task.Result; + int code = Convert.ToInt32(response.StatusCode); + if (code == 200) + { + Task<Stream> task2 = response.Content.ReadAsStreamAsync(); + task2.Wait(); + using (Stream stream = task2.Result) + { + string suffix = Path.GetExtension(response.RequestMessage.RequestUri.ToString()); + using (FileStream fs = new FileStream(absolutePath, FileMode.OpenOrCreate)) + { + byte[] buffer = new byte[1024]; + int readLength = 0; + int length; + while ((length = stream.Read(buffer, 0, buffer.Length)) != 0) + { + readLength += length; + fs.Write(buffer, 0, length); + } + } + } + } + else + { + string error = "鍥剧焊涓嬭浇澶辫触"; + if (response.Headers.TryGetValues("FileName", out IEnumerable<string> values)) + { + error = HttpUtility.UrlDecode(values.First()); + } + throw new CustomWebException(error); + } + } + + /// <summary> + /// 涓嬭浇鏂囦欢鍒版寚瀹氭枃浠跺す + /// </summary> + /// <param name="client"></param> + /// <param name="url"></param> + /// <param name="dir"></param> + /// <param name="fileName"></param> + /// <param name="models"></param> + public static async Task GetDownload(this HttpClient client, string url, string dir, string fileName, params object[] models) + { + foreach (object model in models) + { + url = url.ModelToUriParam(model); + } + HttpResponseMessage response = await client.GetAsync(url); + using (Stream stream = await response.Content.ReadAsStreamAsync()) + { + string suffix = Path.GetExtension(response.RequestMessage.RequestUri.ToString()); + using (FileStream fs = new FileStream($"{dir}/{fileName}", FileMode.CreateNew)) + { + byte[] buffer = new byte[1024]; + int readLength = 0; + int length; + while ((length = await stream.ReadAsync(buffer, 0, buffer.Length)) != 0) + { + readLength += length; + fs.Write(buffer, 0, length); + } + } + } + } + + public static async void GetDownloadWithName(this HttpClient client, string url, string dir, params object[] models) + { + foreach (object model in models) + { + url = url.ModelToUriParam(model); + } + + HttpResponseMessage response = await client.GetAsync(url); + string fileName = HttpUtility.UrlDecode(response.Headers.GetValues("FileName").FirstOrDefault()); + using (Stream stream = await response.Content.ReadAsStreamAsync()) + { + string suffix = Path.GetExtension(response.RequestMessage.RequestUri.ToString()); + using (FileStream fs = new FileStream($"{dir}/{fileName}", FileMode.CreateNew)) + { + byte[] buffer = new byte[1024]; + int readLength = 0; + int length; + while ((length = await stream.ReadAsync(buffer, 0, buffer.Length)) != 0) + { + readLength += length; + fs.Write(buffer, 0, length); + } + } + } + } + + public static string ModelToUriParam(this string url, object obj) + { + PropertyInfo[] properties = obj.GetType().GetProperties(); + StringBuilder sb = new StringBuilder() + .Append(url).Append("?"); + if (obj is Dictionary<string, string>) + { + Dictionary<string, string> dict = (Dictionary<string, string>)obj; + foreach (var item in dict) + { + if (item.Value == null || string.IsNullOrWhiteSpace(item.Value)) + { + continue; + } + sb = sb.Append(item.Key) + .Append("=") + .Append(HttpUtility.UrlEncode(item.Value)) + .Append("&"); + } + } + else + { + foreach (PropertyInfo p in properties) + { + object v = p.GetValue(obj, null); + if (v == null || string.IsNullOrWhiteSpace(v.ToString())) + { + continue; + } + sb = sb.Append(p.Name) + .Append("=") + .Append(HttpUtility.UrlEncode(v.ToString())) + .Append("&"); + } + } + sb = sb.Remove(sb.Length - 1, 1); + return sb.ToString(); + } + } +} diff --git a/PdmAlert/app.manifest b/PdmAlert/app.manifest new file mode 100644 index 0000000..4fddf7e --- /dev/null +++ b/PdmAlert/app.manifest @@ -0,0 +1,79 @@ +锘�<?xml version="1.0" encoding="utf-8"?> +<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> + <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> + <security> + <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> + <!-- UAC 娓呭崟閫夐」 + 濡傛灉鎯宠鏇存敼 Windows 鐢ㄦ埛甯愭埛鎺у埗绾у埆锛岃浣跨敤 + 浠ヤ笅鑺傜偣涔嬩竴鏇挎崲 requestedExecutionLevel 鑺傜偣銆� + + <requestedExecutionLevel level="asInvoker" uiAccess="false" /> + <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> + <requestedExecutionLevel level="highestAvailable" uiAccess="false" /> + + 鎸囧畾 requestedExecutionLevel 鍏冪礌灏嗙鐢ㄦ枃浠跺拰娉ㄥ唽琛ㄨ櫄鎷熷寲銆� + 濡傛灉浣犵殑搴旂敤绋嬪簭闇�瑕佹铏氭嫙鍖栨潵瀹炵幇鍚戝悗鍏煎鎬э紝鍒欑Щ闄ゆ + 鍏冪礌銆� + --> + <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> + </requestedPrivileges> + </security> + </trustInfo> + + <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> + <application> + <!-- 璁捐姝ゅ簲鐢ㄧ▼搴忎笌鍏朵竴璧峰伐浣滀笖宸查拡瀵规搴旂敤绋嬪簭杩涜娴嬭瘯鐨� + Windows 鐗堟湰鐨勫垪琛ㄣ�傚彇娑堣瘎璁洪�傚綋鐨勫厓绱狅紝 + Windows 灏嗚嚜鍔ㄩ�夋嫨鏈�鍏煎鐨勭幆澧冦�� --> + + <!-- Windows Vista --> + <!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />--> + + <!-- Windows 7 --> + <!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />--> + + <!-- Windows 8 --> + <!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />--> + + <!-- Windows 8.1 --> + <!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />--> + + <!-- Windows 10 --> + <!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />--> + + </application> + </compatibility> + + <!-- 鎸囩ず璇ュ簲鐢ㄧ▼搴忓彲鎰熺煡 DPI 涓� Windows 鍦� DPI 杈冮珮鏃跺皢涓嶄細瀵瑰叾杩涜 + 鑷姩缂╂斁銆俉indows Presentation Foundation (WPF)搴旂敤绋嬪簭鑷姩鎰熺煡 DPI锛屾棤闇� + 閫夋嫨鍔犲叆銆傞�夋嫨鍔犲叆姝よ缃殑 Windows 绐椾綋搴旂敤绋嬪簭(闈㈠悜 .NET Framework 4.6)杩樺簲 + 鍦ㄥ叾 app.config 涓皢 "EnableWindowsFormsHighDpiAutoResizing" 璁剧疆璁剧疆涓� "true"銆� + + 灏嗗簲鐢ㄧ▼搴忚涓烘劅鐭ラ暱璺緞銆傝鍙傞槄 https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation --> + <!-- + <application xmlns="urn:schemas-microsoft-com:asm.v3"> + <windowsSettings> + <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware> + <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware> + </windowsSettings> + </application> + --> + + <!-- 鍚敤 Windows 鍏叡鎺т欢鍜屽璇濇鐨勪富棰�(Windows XP 鍜屾洿楂樼増鏈�) --> + <!-- + <dependency> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.Windows.Common-Controls" + version="6.0.0.0" + processorArchitecture="*" + publicKeyToken="6595b64144ccf1df" + language="*" + /> + </dependentAssembly> + </dependency> + --> + +</assembly> diff --git a/PdmAlert/lib/Newtonsoft.Json.dll b/PdmAlert/lib/Newtonsoft.Json.dll new file mode 100644 index 0000000..341d08f --- /dev/null +++ b/PdmAlert/lib/Newtonsoft.Json.dll Binary files differ -- Gitblit v1.9.1