From ca04e0cc6579fa15489a2908575b62fd536bf3a4 Mon Sep 17 00:00:00 2001 From: xiaochanghai Date: Mon, 29 Apr 2024 16:38:31 +0800 Subject: [PATCH] 1 --- Tiobon.Core.sln | 7 + Tiobon.PublishHelper/Frm/Form1.Designer.cs | 115 ++++ Tiobon.PublishHelper/Frm/Form1.cs | 20 + Tiobon.PublishHelper/Frm/Form1.resx | 136 ++++ .../Frm/Form_DevServer.Designer.cs | 187 ++++++ Tiobon.PublishHelper/Frm/Form_DevServer.cs | 100 +++ Tiobon.PublishHelper/Frm/Form_DevServer.resx | 123 ++++ .../Frm/Form_DevServer_Item.Designer.cs | 239 +++++++ .../Frm/Form_DevServer_Item.cs | 96 +++ .../Frm/Form_DevServer_Item.resx | 120 ++++ .../Frm/Form_Hospital.Designer.cs | 186 ++++++ Tiobon.PublishHelper/Frm/Form_Hospital.cs | 188 ++++++ Tiobon.PublishHelper/Frm/Form_Hospital.resx | 123 ++++ .../Frm/Form_Hospital_Item.Designer.cs | 241 +++++++ .../Frm/Form_Hospital_Item.cs | 119 ++++ .../Frm/Form_Hospital_Item.resx | 120 ++++ Tiobon.PublishHelper/Program.cs | 17 + Tiobon.PublishHelper/Src/CmdHelper.cs | 84 +++ Tiobon.PublishHelper/Src/DevServer.cs | 72 +++ Tiobon.PublishHelper/Src/DockerCommand.cs | 105 +++ Tiobon.PublishHelper/Src/OprateLog.cs | 125 ++++ Tiobon.PublishHelper/Src/PublishServer.cs | 79 +++ Tiobon.PublishHelper/Src/SftpHelper.cs | 503 +++++++++++++++ Tiobon.PublishHelper/Src/SshHelper.cs | 249 +++++++ Tiobon.PublishHelper/Src/Utility.cs | 610 ++++++++++++++++++ Tiobon.PublishHelper/Src/ZipHelper.cs | 56 ++ .../Tiobon.PublishHelper.csproj | 33 + 27 files changed, 4053 insertions(+) create mode 100644 Tiobon.PublishHelper/Frm/Form1.Designer.cs create mode 100644 Tiobon.PublishHelper/Frm/Form1.cs create mode 100644 Tiobon.PublishHelper/Frm/Form1.resx create mode 100644 Tiobon.PublishHelper/Frm/Form_DevServer.Designer.cs create mode 100644 Tiobon.PublishHelper/Frm/Form_DevServer.cs create mode 100644 Tiobon.PublishHelper/Frm/Form_DevServer.resx create mode 100644 Tiobon.PublishHelper/Frm/Form_DevServer_Item.Designer.cs create mode 100644 Tiobon.PublishHelper/Frm/Form_DevServer_Item.cs create mode 100644 Tiobon.PublishHelper/Frm/Form_DevServer_Item.resx create mode 100644 Tiobon.PublishHelper/Frm/Form_Hospital.Designer.cs create mode 100644 Tiobon.PublishHelper/Frm/Form_Hospital.cs create mode 100644 Tiobon.PublishHelper/Frm/Form_Hospital.resx create mode 100644 Tiobon.PublishHelper/Frm/Form_Hospital_Item.Designer.cs create mode 100644 Tiobon.PublishHelper/Frm/Form_Hospital_Item.cs create mode 100644 Tiobon.PublishHelper/Frm/Form_Hospital_Item.resx create mode 100644 Tiobon.PublishHelper/Program.cs create mode 100644 Tiobon.PublishHelper/Src/CmdHelper.cs create mode 100644 Tiobon.PublishHelper/Src/DevServer.cs create mode 100644 Tiobon.PublishHelper/Src/DockerCommand.cs create mode 100644 Tiobon.PublishHelper/Src/OprateLog.cs create mode 100644 Tiobon.PublishHelper/Src/PublishServer.cs create mode 100644 Tiobon.PublishHelper/Src/SftpHelper.cs create mode 100644 Tiobon.PublishHelper/Src/SshHelper.cs create mode 100644 Tiobon.PublishHelper/Src/Utility.cs create mode 100644 Tiobon.PublishHelper/Src/ZipHelper.cs create mode 100644 Tiobon.PublishHelper/Tiobon.PublishHelper.csproj diff --git a/Tiobon.Core.sln b/Tiobon.Core.sln index f654fcb7..781ac8f3 100644 --- a/Tiobon.Core.sln +++ b/Tiobon.Core.sln @@ -68,6 +68,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tiobon.Core.OPS.Tool", "Tio EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tiobon.Core.PublishHelper", "Tiobon.Core.PublishHelper\Tiobon.Core.PublishHelper.csproj", "{27648B22-ECC7-4B2F-BB85-A86C03B6ED05}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tiobon.PublishHelper", "Tiobon.PublishHelper\Tiobon.PublishHelper.csproj", "{16F70A02-56E3-480B-AF2D-2E9429D05A92}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -150,6 +152,10 @@ Global {27648B22-ECC7-4B2F-BB85-A86C03B6ED05}.Debug|Any CPU.Build.0 = Debug|Any CPU {27648B22-ECC7-4B2F-BB85-A86C03B6ED05}.Release|Any CPU.ActiveCfg = Release|Any CPU {27648B22-ECC7-4B2F-BB85-A86C03B6ED05}.Release|Any CPU.Build.0 = Release|Any CPU + {16F70A02-56E3-480B-AF2D-2E9429D05A92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {16F70A02-56E3-480B-AF2D-2E9429D05A92}.Debug|Any CPU.Build.0 = Debug|Any CPU + {16F70A02-56E3-480B-AF2D-2E9429D05A92}.Release|Any CPU.ActiveCfg = Release|Any CPU + {16F70A02-56E3-480B-AF2D-2E9429D05A92}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -163,6 +169,7 @@ Global {BA7081E8-08F2-4CC2-ACD9-E878C0CDE313} = {047A9723-9AAC-42E3-8C69-B3835F15FF96} {1C0E27D6-B516-4D30-B559-C9097476DEEC} = {047A9723-9AAC-42E3-8C69-B3835F15FF96} {27648B22-ECC7-4B2F-BB85-A86C03B6ED05} = {047A9723-9AAC-42E3-8C69-B3835F15FF96} + {16F70A02-56E3-480B-AF2D-2E9429D05A92} = {047A9723-9AAC-42E3-8C69-B3835F15FF96} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {AB40D0C5-E3EA-4A9B-86C2-38F0BB33FC04} diff --git a/Tiobon.PublishHelper/Frm/Form1.Designer.cs b/Tiobon.PublishHelper/Frm/Form1.Designer.cs new file mode 100644 index 00000000..82ca2e84 --- /dev/null +++ b/Tiobon.PublishHelper/Frm/Form1.Designer.cs @@ -0,0 +1,115 @@ +namespace Tiobon.PublishHelper +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1)); + toolStrip1 = new ToolStrip(); + toolStripDropDownButton1 = new ToolStripDropDownButton(); + toolStripMenuItem2 = new ToolStripMenuItem(); + statusStrip1 = new StatusStrip(); + toolStripStatusLabel1 = new ToolStripStatusLabel(); + toolStripStatusLabel2 = new ToolStripStatusLabel(); + toolStrip1.SuspendLayout(); + statusStrip1.SuspendLayout(); + SuspendLayout(); + // + // toolStrip1 + // + toolStrip1.Items.AddRange(new ToolStripItem[] { toolStripDropDownButton1 }); + toolStrip1.Location = new Point(0, 0); + toolStrip1.Name = "toolStrip1"; + toolStrip1.Size = new Size(800, 25); + toolStrip1.TabIndex = 0; + toolStrip1.Text = "toolStrip1"; + // + // toolStripDropDownButton1 + // + toolStripDropDownButton1.DisplayStyle = ToolStripItemDisplayStyle.Text; + toolStripDropDownButton1.DropDownItems.AddRange(new ToolStripItem[] { toolStripMenuItem2 }); + toolStripDropDownButton1.Image = (Image)resources.GetObject("toolStripDropDownButton1.Image"); + toolStripDropDownButton1.ImageTransparentColor = Color.Magenta; + toolStripDropDownButton1.Name = "toolStripDropDownButton1"; + toolStripDropDownButton1.Size = new Size(45, 22); + toolStripDropDownButton1.Text = "管理"; + // + // toolStripMenuItem2 + // + toolStripMenuItem2.Name = "toolStripMenuItem2"; + toolStripMenuItem2.Size = new Size(180, 22); + toolStripMenuItem2.Text = "开发服务器"; + toolStripMenuItem2.Click += toolStripMenuItem2_Click; + // + // statusStrip1 + // + statusStrip1.Items.AddRange(new ToolStripItem[] { toolStripStatusLabel1, toolStripStatusLabel2 }); + statusStrip1.Location = new Point(0, 428); + statusStrip1.Name = "statusStrip1"; + statusStrip1.Size = new Size(800, 22); + statusStrip1.TabIndex = 1; + statusStrip1.Text = "statusStrip1"; + // + // toolStripStatusLabel1 + // + toolStripStatusLabel1.Name = "toolStripStatusLabel1"; + toolStripStatusLabel1.Size = new Size(131, 17); + toolStripStatusLabel1.Text = "toolStripStatusLabel1"; + // + // toolStripStatusLabel2 + // + toolStripStatusLabel2.Name = "toolStripStatusLabel2"; + toolStripStatusLabel2.Size = new Size(131, 17); + toolStripStatusLabel2.Text = "toolStripStatusLabel2"; + // + // Form1 + // + AutoScaleDimensions = new SizeF(7F, 17F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(800, 450); + Controls.Add(statusStrip1); + Controls.Add(toolStrip1); + Name = "Form1"; + Text = "开发工具"; + toolStrip1.ResumeLayout(false); + toolStrip1.PerformLayout(); + statusStrip1.ResumeLayout(false); + statusStrip1.PerformLayout(); + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private ToolStrip toolStrip1; + private ToolStripDropDownButton toolStripDropDownButton1; + private ToolStripMenuItem toolStripMenuItem2; + private StatusStrip statusStrip1; + private ToolStripStatusLabel toolStripStatusLabel1; + private ToolStripStatusLabel toolStripStatusLabel2; + } +} diff --git a/Tiobon.PublishHelper/Frm/Form1.cs b/Tiobon.PublishHelper/Frm/Form1.cs new file mode 100644 index 00000000..538dccef --- /dev/null +++ b/Tiobon.PublishHelper/Frm/Form1.cs @@ -0,0 +1,20 @@ +namespace Tiobon.PublishHelper +{ + public partial class Form1 : Form + { + public Form1() + { + InitializeComponent(); + } + + #region + private void toolStripMenuItem2_Click(object sender, EventArgs e) + { + using (Form_DevServer f = new Form_DevServer()) + { + f.ShowDialog(); + } + } + #endregion + } +} diff --git a/Tiobon.PublishHelper/Frm/Form1.resx b/Tiobon.PublishHelper/Frm/Form1.resx new file mode 100644 index 00000000..7369773a --- /dev/null +++ b/Tiobon.PublishHelper/Frm/Form1.resx @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACRSURBVDhPY/j27dt/SjDYACcnJ7IwigEf3n8kCZNswPNb + J/+f6DYF0yA+yQac6Db5f6hWCmwIiE+mC0wIu2DS2Vf/F1x6DefjwlgNyNr34r/0wkdgTMgQDAOQNRNj + CIoBOg0rMTTDMLIhIHbriZeYBmDTiIxBGkEYxge5liQDsGGQqykyAISpZwAlmIEywMAAAAc1/Jwvt6sN + AAAAAElFTkSuQmCC + + + + 129, 17 + + \ No newline at end of file diff --git a/Tiobon.PublishHelper/Frm/Form_DevServer.Designer.cs b/Tiobon.PublishHelper/Frm/Form_DevServer.Designer.cs new file mode 100644 index 00000000..77d44bae --- /dev/null +++ b/Tiobon.PublishHelper/Frm/Form_DevServer.Designer.cs @@ -0,0 +1,187 @@ +namespace Tiobon.PublishHelper +{ + partial class Form_DevServer + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.gb_Main = new System.Windows.Forms.GroupBox(); + this.listView_Dev = new System.Windows.Forms.ListView(); + this.DevName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.IP = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.UserName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.Password = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.SuPassword = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.Port = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.contextMenuStrip_ListView = new System.Windows.Forms.ContextMenuStrip(this.components); + this.tsmi_Insert = new System.Windows.Forms.ToolStripMenuItem(); + this.tsmi_Edit = new System.Windows.Forms.ToolStripMenuItem(); + this.tsmi_Delete = new System.Windows.Forms.ToolStripMenuItem(); + this.tsmi_Hospital = new System.Windows.Forms.ToolStripMenuItem(); + this.gb_Main.SuspendLayout(); + this.contextMenuStrip_ListView.SuspendLayout(); + this.SuspendLayout(); + // + // gb_Main + // + this.gb_Main.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gb_Main.Controls.Add(this.listView_Dev); + this.gb_Main.Location = new System.Drawing.Point(12, 12); + this.gb_Main.Name = "gb_Main"; + this.gb_Main.Size = new System.Drawing.Size(776, 426); + this.gb_Main.TabIndex = 0; + this.gb_Main.TabStop = false; + // + // listView_Dev + // + this.listView_Dev.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.DevName, + this.IP, + this.UserName, + this.Password, + this.SuPassword, + this.Port}); + this.listView_Dev.ContextMenuStrip = this.contextMenuStrip_ListView; + this.listView_Dev.Dock = System.Windows.Forms.DockStyle.Fill; + this.listView_Dev.FullRowSelect = true; + this.listView_Dev.GridLines = true; + this.listView_Dev.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.listView_Dev.HideSelection = false; + this.listView_Dev.Location = new System.Drawing.Point(3, 17); + this.listView_Dev.MultiSelect = false; + this.listView_Dev.Name = "listView_Dev"; + this.listView_Dev.Size = new System.Drawing.Size(770, 406); + this.listView_Dev.TabIndex = 0; + this.listView_Dev.UseCompatibleStateImageBehavior = false; + this.listView_Dev.View = System.Windows.Forms.View.Details; + this.listView_Dev.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.listView_Dev_MouseDoubleClick); + // + // DevName + // + this.DevName.Text = "名称"; + this.DevName.Width = 100; + // + // IP + // + this.IP.Text = "Ip"; + this.IP.Width = 150; + // + // UserName + // + this.UserName.Text = "用户名"; + this.UserName.Width = 150; + // + // Password + // + this.Password.Text = "密码"; + this.Password.Width = 150; + // + // SuPassword + // + this.SuPassword.Text = "Su密码"; + this.SuPassword.Width = 150; + // + // Port + // + this.Port.Text = "端口"; + this.Port.Width = 50; + // + // contextMenuStrip_ListView + // + this.contextMenuStrip_ListView.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.tsmi_Insert, + this.tsmi_Edit, + this.tsmi_Delete, + this.tsmi_Hospital}); + this.contextMenuStrip_ListView.Name = "contextMenuStrip_Main"; + this.contextMenuStrip_ListView.Size = new System.Drawing.Size(142, 92); + // + // tsmi_Insert + // + this.tsmi_Insert.Name = "tsmi_Insert"; + this.tsmi_Insert.Size = new System.Drawing.Size(141, 22); + this.tsmi_Insert.Text = "新增(&N)"; + this.tsmi_Insert.Click += new System.EventHandler(this.tsmi_Insert_Click); + // + // tsmi_Edit + // + this.tsmi_Edit.Name = "tsmi_Edit"; + this.tsmi_Edit.Size = new System.Drawing.Size(141, 22); + this.tsmi_Edit.Text = "编辑(&E)"; + this.tsmi_Edit.Click += new System.EventHandler(this.tsmi_Edit_Click); + // + // tsmi_Delete + // + this.tsmi_Delete.Name = "tsmi_Delete"; + this.tsmi_Delete.Size = new System.Drawing.Size(141, 22); + this.tsmi_Delete.Text = "删除(&D)"; + this.tsmi_Delete.Click += new System.EventHandler(this.tsmi_Delete_Click); + // + // tsmi_Hospital + // + this.tsmi_Hospital.Name = "tsmi_Hospital"; + this.tsmi_Hospital.Size = new System.Drawing.Size(141, 22); + this.tsmi_Hospital.Text = "项目管理(&H)"; + this.tsmi_Hospital.Click += new System.EventHandler(this.tsmi_Hospital_Click); + // + // Form_DevServer + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Controls.Add(this.gb_Main); + this.Name = "Form_DevServer"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "开发服务器"; + this.Load += new System.EventHandler(this.Form_DevServer_Load); + this.gb_Main.ResumeLayout(false); + this.contextMenuStrip_ListView.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox gb_Main; + private System.Windows.Forms.ListView listView_Dev; + private System.Windows.Forms.ColumnHeader DevName; + private System.Windows.Forms.ColumnHeader IP; + private System.Windows.Forms.ColumnHeader UserName; + private System.Windows.Forms.ColumnHeader Password; + private System.Windows.Forms.ColumnHeader SuPassword; + private System.Windows.Forms.ColumnHeader Port; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip_ListView; + private System.Windows.Forms.ToolStripMenuItem tsmi_Insert; + private System.Windows.Forms.ToolStripMenuItem tsmi_Edit; + private System.Windows.Forms.ToolStripMenuItem tsmi_Delete; + private System.Windows.Forms.ToolStripMenuItem tsmi_Hospital; + } +} \ No newline at end of file diff --git a/Tiobon.PublishHelper/Frm/Form_DevServer.cs b/Tiobon.PublishHelper/Frm/Form_DevServer.cs new file mode 100644 index 00000000..e34f599f --- /dev/null +++ b/Tiobon.PublishHelper/Frm/Form_DevServer.cs @@ -0,0 +1,100 @@ +using System.Data; + +namespace Tiobon.PublishHelper +{ + public partial class Form_DevServer : Form + { + public Form_DevServer() + { + InitializeComponent(); + } + + private void Form_DevServer_Load(object sender, EventArgs e) + { + RefreshView(); + } + + private void tsmi_Insert_Click(object sender, EventArgs e) + { + using (Form_DevServer_Item f = new Form_DevServer_Item("新增")) + { + f.ShowDialog(); + } + Utility.SaveDevServer(); + RefreshView(); + } + + private void tsmi_Edit_Click(object sender, EventArgs e) + { + if (this.listView_Dev.SelectedItems.Count <= 0) + return; + using (Form_DevServer_Item f = new Form_DevServer_Item($"编辑 - {this.listView_Dev.SelectedItems[0].Text}")) + { + f.ShowDialog(); + } + Utility.SaveDevServer(); + RefreshView(); + } + + private void tsmi_Delete_Click(object sender, EventArgs e) + { + if (this.listView_Dev.SelectedItems.Count <= 0) + { + return; + } + if (MessageBox.Show("是否确认删除?", "提示", MessageBoxButtons.YesNo) != DialogResult.Yes) + { + return; + } + var item = Utility.m_DevServers.Where(o => o.Name == this.listView_Dev.SelectedItems[0].Text).FirstOrDefault(); + if (!(item is null)) + { + Utility.m_DevServers.Remove(item); + Utility.SaveDevServer(); + RefreshView(); + } + } + + private void RefreshView() + { + listView_Dev.Items.Clear(); + Utility.m_DevServers.ForEach(o => + { + ListViewItem item = new ListViewItem(); + item.SubItems[0].Text = o.Name; + item.SubItems.Add(o.Ip); + item.SubItems.Add(o.UserName); + item.SubItems.Add(o.Password); + item.SubItems.Add(o.SuPassword); + item.SubItems.Add(o.Port.ToString()); + listView_Dev.Items.Add(item); + }); + } + + private void tsmi_Hospital_Click(object sender, EventArgs e) + { + if (this.listView_Dev.SelectedItems.Count <= 0) + { + return; + } + using (Form_Hospital f = new Form_Hospital(this.listView_Dev.SelectedItems[0].Text)) + { + f.ShowDialog(); + } + Utility.SaveDevServer(); + } + + private void listView_Dev_MouseDoubleClick(object sender, MouseEventArgs e) + { + if (this.listView_Dev.SelectedItems.Count <= 0) + { + return; + } + using (Form_Hospital f = new Form_Hospital(this.listView_Dev.SelectedItems[0].Text)) + { + f.ShowDialog(); + } + Utility.SaveDevServer(); + } + } +} diff --git a/Tiobon.PublishHelper/Frm/Form_DevServer.resx b/Tiobon.PublishHelper/Frm/Form_DevServer.resx new file mode 100644 index 00000000..f548663f --- /dev/null +++ b/Tiobon.PublishHelper/Frm/Form_DevServer.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/Tiobon.PublishHelper/Frm/Form_DevServer_Item.Designer.cs b/Tiobon.PublishHelper/Frm/Form_DevServer_Item.Designer.cs new file mode 100644 index 00000000..1d202b4f --- /dev/null +++ b/Tiobon.PublishHelper/Frm/Form_DevServer_Item.Designer.cs @@ -0,0 +1,239 @@ +namespace Tiobon.PublishHelper +{ + partial class Form_DevServer_Item + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.gb_main = new System.Windows.Forms.GroupBox(); + this.txt_UserName = new System.Windows.Forms.TextBox(); + this.lbl_UserName = new System.Windows.Forms.Label(); + this.txt_Port = new System.Windows.Forms.TextBox(); + this.lbl_Port = new System.Windows.Forms.Label(); + this.txt_SuPassword = new System.Windows.Forms.TextBox(); + this.lbl_SuPassword = new System.Windows.Forms.Label(); + this.txt_Password = new System.Windows.Forms.TextBox(); + this.lbl_Password = new System.Windows.Forms.Label(); + this.txt_Ip = new System.Windows.Forms.TextBox(); + this.lbl_Ip = new System.Windows.Forms.Label(); + this.txt_Name = new System.Windows.Forms.TextBox(); + this.lbl_Name = new System.Windows.Forms.Label(); + this.btn_Ok = new System.Windows.Forms.Button(); + this.btn_Cancel = new System.Windows.Forms.Button(); + this.gb_main.SuspendLayout(); + this.SuspendLayout(); + // + // gb_main + // + this.gb_main.Controls.Add(this.txt_UserName); + this.gb_main.Controls.Add(this.lbl_UserName); + this.gb_main.Controls.Add(this.txt_Port); + this.gb_main.Controls.Add(this.lbl_Port); + this.gb_main.Controls.Add(this.txt_SuPassword); + this.gb_main.Controls.Add(this.lbl_SuPassword); + this.gb_main.Controls.Add(this.txt_Password); + this.gb_main.Controls.Add(this.lbl_Password); + this.gb_main.Controls.Add(this.txt_Ip); + this.gb_main.Controls.Add(this.lbl_Ip); + this.gb_main.Controls.Add(this.txt_Name); + this.gb_main.Controls.Add(this.lbl_Name); + this.gb_main.Location = new System.Drawing.Point(12, 12); + this.gb_main.Name = "gb_main"; + this.gb_main.Size = new System.Drawing.Size(270, 219); + this.gb_main.TabIndex = 0; + this.gb_main.TabStop = false; + // + // txt_UserName + // + this.txt_UserName.Location = new System.Drawing.Point(105, 86); + this.txt_UserName.Name = "txt_UserName"; + this.txt_UserName.Size = new System.Drawing.Size(144, 21); + this.txt_UserName.TabIndex = 16; + this.txt_UserName.Text = "huhangmed"; + // + // lbl_UserName + // + this.lbl_UserName.AutoSize = true; + this.lbl_UserName.Location = new System.Drawing.Point(22, 89); + this.lbl_UserName.Name = "lbl_UserName"; + this.lbl_UserName.Size = new System.Drawing.Size(47, 12); + this.lbl_UserName.TabIndex = 17; + this.lbl_UserName.Text = "用户名:"; + this.lbl_UserName.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // txt_Port + // + this.txt_Port.Location = new System.Drawing.Point(105, 185); + this.txt_Port.Name = "txt_Port"; + this.txt_Port.Size = new System.Drawing.Size(144, 21); + this.txt_Port.TabIndex = 14; + this.txt_Port.Text = "22"; + // + // lbl_Port + // + this.lbl_Port.AutoSize = true; + this.lbl_Port.Location = new System.Drawing.Point(22, 188); + this.lbl_Port.Name = "lbl_Port"; + this.lbl_Port.Size = new System.Drawing.Size(53, 12); + this.lbl_Port.TabIndex = 15; + this.lbl_Port.Text = "SSH端口:"; + this.lbl_Port.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // txt_SuPassword + // + this.txt_SuPassword.Location = new System.Drawing.Point(105, 152); + this.txt_SuPassword.Name = "txt_SuPassword"; + this.txt_SuPassword.Size = new System.Drawing.Size(144, 21); + this.txt_SuPassword.TabIndex = 12; + this.txt_SuPassword.Text = "Huhang@2019"; + // + // lbl_SuPassword + // + this.lbl_SuPassword.AutoSize = true; + this.lbl_SuPassword.Location = new System.Drawing.Point(22, 155); + this.lbl_SuPassword.Name = "lbl_SuPassword"; + this.lbl_SuPassword.Size = new System.Drawing.Size(47, 12); + this.lbl_SuPassword.TabIndex = 13; + this.lbl_SuPassword.Text = "SU密码:"; + this.lbl_SuPassword.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // txt_Password + // + this.txt_Password.Location = new System.Drawing.Point(105, 119); + this.txt_Password.Name = "txt_Password"; + this.txt_Password.Size = new System.Drawing.Size(144, 21); + this.txt_Password.TabIndex = 10; + this.txt_Password.Text = "Huhangmed@2019"; + // + // lbl_Password + // + this.lbl_Password.AutoSize = true; + this.lbl_Password.Location = new System.Drawing.Point(22, 122); + this.lbl_Password.Name = "lbl_Password"; + this.lbl_Password.Size = new System.Drawing.Size(35, 12); + this.lbl_Password.TabIndex = 11; + this.lbl_Password.Text = "密码:"; + this.lbl_Password.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // txt_Ip + // + this.txt_Ip.Location = new System.Drawing.Point(105, 53); + this.txt_Ip.Name = "txt_Ip"; + this.txt_Ip.Size = new System.Drawing.Size(144, 21); + this.txt_Ip.TabIndex = 8; + this.txt_Ip.Text = "192.168.8.72"; + // + // lbl_Ip + // + this.lbl_Ip.AutoSize = true; + this.lbl_Ip.Location = new System.Drawing.Point(22, 56); + this.lbl_Ip.Name = "lbl_Ip"; + this.lbl_Ip.Size = new System.Drawing.Size(59, 12); + this.lbl_Ip.TabIndex = 9; + this.lbl_Ip.Text = "服务器IP:"; + this.lbl_Ip.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // txt_Name + // + this.txt_Name.Location = new System.Drawing.Point(105, 20); + this.txt_Name.Name = "txt_Name"; + this.txt_Name.Size = new System.Drawing.Size(144, 21); + this.txt_Name.TabIndex = 6; + this.txt_Name.Text = "dev-72"; + // + // lbl_Name + // + this.lbl_Name.AutoSize = true; + this.lbl_Name.Location = new System.Drawing.Point(22, 23); + this.lbl_Name.Name = "lbl_Name"; + this.lbl_Name.Size = new System.Drawing.Size(71, 12); + this.lbl_Name.TabIndex = 7; + this.lbl_Name.Text = "服务器名称:"; + this.lbl_Name.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // btn_Ok + // + this.btn_Ok.Location = new System.Drawing.Point(36, 249); + this.btn_Ok.Name = "btn_Ok"; + this.btn_Ok.Size = new System.Drawing.Size(75, 23); + this.btn_Ok.TabIndex = 1; + this.btn_Ok.Text = "确定(&O)"; + this.btn_Ok.UseVisualStyleBackColor = true; + this.btn_Ok.Click += new System.EventHandler(this.btn_Ok_Click); + // + // btn_Cancel + // + this.btn_Cancel.Location = new System.Drawing.Point(186, 249); + this.btn_Cancel.Name = "btn_Cancel"; + this.btn_Cancel.Size = new System.Drawing.Size(75, 23); + this.btn_Cancel.TabIndex = 2; + this.btn_Cancel.Text = "取消(&C)"; + this.btn_Cancel.UseVisualStyleBackColor = true; + this.btn_Cancel.Click += new System.EventHandler(this.btn_Cancel_Click); + // + // Form_DevServer_Item + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(296, 284); + this.Controls.Add(this.btn_Cancel); + this.Controls.Add(this.btn_Ok); + this.Controls.Add(this.gb_main); + this.MaximizeBox = false; + this.MaximumSize = new System.Drawing.Size(312, 323); + this.MinimizeBox = false; + this.MinimumSize = new System.Drawing.Size(312, 323); + this.Name = "Form_DevServer_Item"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "新增"; + this.Load += new System.EventHandler(this.Form_DevServer_Item_Load); + this.gb_main.ResumeLayout(false); + this.gb_main.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox gb_main; + private System.Windows.Forms.TextBox txt_SuPassword; + private System.Windows.Forms.Label lbl_SuPassword; + private System.Windows.Forms.TextBox txt_Password; + private System.Windows.Forms.Label lbl_Password; + private System.Windows.Forms.TextBox txt_Ip; + private System.Windows.Forms.Label lbl_Ip; + private System.Windows.Forms.TextBox txt_Name; + private System.Windows.Forms.Label lbl_Name; + private System.Windows.Forms.TextBox txt_Port; + private System.Windows.Forms.Label lbl_Port; + private System.Windows.Forms.Button btn_Ok; + private System.Windows.Forms.Button btn_Cancel; + private System.Windows.Forms.TextBox txt_UserName; + private System.Windows.Forms.Label lbl_UserName; + } +} \ No newline at end of file diff --git a/Tiobon.PublishHelper/Frm/Form_DevServer_Item.cs b/Tiobon.PublishHelper/Frm/Form_DevServer_Item.cs new file mode 100644 index 00000000..ef712234 --- /dev/null +++ b/Tiobon.PublishHelper/Frm/Form_DevServer_Item.cs @@ -0,0 +1,96 @@ +using System.Data; + +namespace Tiobon.PublishHelper +{ + public partial class Form_DevServer_Item : Form + { + bool b_edit = false; + public Form_DevServer_Item(string name) + { + InitializeComponent(); + this.Text = name; + b_edit = this.Text != "新增"; + } + + private void Form_DevServer_Item_Load(object sender, EventArgs e) + { + if (b_edit) + { + var item = Utility.m_DevServers.Where(o => o.Name == this.Text.Split(new string[] { " - " }, StringSplitOptions.RemoveEmptyEntries)[1]).FirstOrDefault(); + if (!(item is null)) + { + this.txt_Name.Text = item.Name; + this.txt_Ip.Text = item.Ip; + this.txt_UserName.Text = item.UserName; + this.txt_Password.Text = item.Password; + this.txt_SuPassword.Text = item.SuPassword; + this.txt_Port.Text = item.Port.ToString(); + } + } + } + + private void btn_Ok_Click(object sender, EventArgs e) + { + foreach (var control in gb_main.Controls) + { + if (control is TextBox) + { + var textBox = control as TextBox; + if (string.IsNullOrEmpty(textBox.Text.Trim())) + { + MessageBox.Show($"{textBox.Name},不允许为空!", "提示"); + return; + } + } + } + var devServer = new DevServer + { + Name = this.txt_Name.Text.Trim(), + Ip = this.txt_Ip.Text.Trim(), + UserName = this.txt_UserName.Text.Trim(), + Password = this.txt_Password.Text.Trim(), + SuPassword = this.txt_SuPassword.Text.Trim(), + Port = int.Parse(this.txt_Port.Text), + Hospitals = new List() + }; + if (b_edit) + { + var nameOld = this.Text.Split(new string[] { " - " }, StringSplitOptions.RemoveEmptyEntries)[1]; + if (nameOld != this.txt_Name.Text.Trim()) + { + if (Utility.m_DevServers.Any(o => o.Name == this.txt_Name.Text.Trim())) + { + MessageBox.Show($"服务器名称已存在!", "提示"); + return; + } + Utility.m_DevServers.Add(devServer); + } + else + { + var item = Utility.m_DevServers.Where(o => o.Name == this.txt_Name.Text.Trim()).FirstOrDefault(); + if (!(item is null)) + { + devServer.Hospitals = item.Hospitals; + Utility.m_DevServers.Remove(item); + Utility.m_DevServers.Add(devServer); + } + } + } + else + { + if (Utility.m_DevServers.Any(o => o.Name == this.txt_Name.Text.Trim())) + { + MessageBox.Show($"服务器名称已存在!", "提示"); + return; + } + Utility.m_DevServers.Add(devServer); + } + this.Close(); + } + + private void btn_Cancel_Click(object sender, EventArgs e) + { + this.Close(); + } + } +} diff --git a/Tiobon.PublishHelper/Frm/Form_DevServer_Item.resx b/Tiobon.PublishHelper/Frm/Form_DevServer_Item.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/Tiobon.PublishHelper/Frm/Form_DevServer_Item.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Tiobon.PublishHelper/Frm/Form_Hospital.Designer.cs b/Tiobon.PublishHelper/Frm/Form_Hospital.Designer.cs new file mode 100644 index 00000000..80648c74 --- /dev/null +++ b/Tiobon.PublishHelper/Frm/Form_Hospital.Designer.cs @@ -0,0 +1,186 @@ +namespace Tiobon.PublishHelper +{ + partial class Form_Hospital + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.gb_Main = new System.Windows.Forms.GroupBox(); + this.ll_Sync = new System.Windows.Forms.LinkLabel(); + this.listView_Hospital = new System.Windows.Forms.ListView(); + this.HospitalName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.FileName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.DefaultPort = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.SCPath = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.WWWPath = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.contextMenuStrip_ListView = new System.Windows.Forms.ContextMenuStrip(this.components); + this.tsmi_Insert = new System.Windows.Forms.ToolStripMenuItem(); + this.tsmi_Edit = new System.Windows.Forms.ToolStripMenuItem(); + this.tsmi_Delete = new System.Windows.Forms.ToolStripMenuItem(); + this.gb_Main.SuspendLayout(); + this.contextMenuStrip_ListView.SuspendLayout(); + this.SuspendLayout(); + // + // gb_Main + // + this.gb_Main.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gb_Main.Controls.Add(this.ll_Sync); + this.gb_Main.Controls.Add(this.listView_Hospital); + this.gb_Main.Location = new System.Drawing.Point(12, 12); + this.gb_Main.Name = "gb_Main"; + this.gb_Main.Size = new System.Drawing.Size(776, 426); + this.gb_Main.TabIndex = 1; + this.gb_Main.TabStop = false; + // + // ll_Sync + // + this.ll_Sync.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.ll_Sync.AutoSize = true; + this.ll_Sync.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline; + this.ll_Sync.Location = new System.Drawing.Point(707, 2); + this.ll_Sync.Name = "ll_Sync"; + this.ll_Sync.Size = new System.Drawing.Size(53, 12); + this.ll_Sync.TabIndex = 1; + this.ll_Sync.TabStop = true; + this.ll_Sync.Text = "同步项目"; + this.ll_Sync.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.ll_Sync_LinkClicked); + // + // listView_Hospital + // + this.listView_Hospital.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.HospitalName, + this.FileName, + this.DefaultPort, + this.SCPath, + this.WWWPath}); + this.listView_Hospital.ContextMenuStrip = this.contextMenuStrip_ListView; + this.listView_Hospital.Dock = System.Windows.Forms.DockStyle.Fill; + this.listView_Hospital.FullRowSelect = true; + this.listView_Hospital.GridLines = true; + this.listView_Hospital.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.listView_Hospital.HideSelection = false; + this.listView_Hospital.Location = new System.Drawing.Point(3, 17); + this.listView_Hospital.MultiSelect = false; + this.listView_Hospital.Name = "listView_Hospital"; + this.listView_Hospital.Size = new System.Drawing.Size(770, 406); + this.listView_Hospital.TabIndex = 0; + this.listView_Hospital.UseCompatibleStateImageBehavior = false; + this.listView_Hospital.View = System.Windows.Forms.View.Details; + this.listView_Hospital.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.listView_Hospital_MouseDoubleClick); + // + // HospitalName + // + this.HospitalName.Text = "项目名称"; + this.HospitalName.Width = 175; + // + // FileName + // + this.FileName.Text = "文件夹名称"; + this.FileName.Width = 87; + // + // DefaultPort + // + this.DefaultPort.Text = "默认端口(前三位)"; + this.DefaultPort.Width = 120; + // + // SCPath + // + this.SCPath.Text = "本地后端代码路径"; + this.SCPath.Width = 205; + // + // WWWPath + // + this.WWWPath.Text = "本地前端代码路径"; + this.WWWPath.Width = 176; + // + // contextMenuStrip_ListView + // + this.contextMenuStrip_ListView.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.tsmi_Insert, + this.tsmi_Edit, + this.tsmi_Delete}); + this.contextMenuStrip_ListView.Name = "contextMenuStrip_Main"; + this.contextMenuStrip_ListView.Size = new System.Drawing.Size(119, 70); + // + // tsmi_Insert + // + this.tsmi_Insert.Name = "tsmi_Insert"; + this.tsmi_Insert.Size = new System.Drawing.Size(118, 22); + this.tsmi_Insert.Text = "新增(&N)"; + this.tsmi_Insert.Click += new System.EventHandler(this.tsmi_Insert_Click); + // + // tsmi_Edit + // + this.tsmi_Edit.Name = "tsmi_Edit"; + this.tsmi_Edit.Size = new System.Drawing.Size(118, 22); + this.tsmi_Edit.Text = "编辑(&E)"; + this.tsmi_Edit.Click += new System.EventHandler(this.tsmi_Edit_Click); + // + // tsmi_Delete + // + this.tsmi_Delete.Name = "tsmi_Delete"; + this.tsmi_Delete.Size = new System.Drawing.Size(118, 22); + this.tsmi_Delete.Text = "删除(&D)"; + this.tsmi_Delete.Click += new System.EventHandler(this.tsmi_Delete_Click); + // + // Form_Hospital + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Controls.Add(this.gb_Main); + this.Name = "Form_Hospital"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "项目配置"; + this.Load += new System.EventHandler(this.Form_Hospital_Load); + this.gb_Main.ResumeLayout(false); + this.gb_Main.PerformLayout(); + this.contextMenuStrip_ListView.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox gb_Main; + private System.Windows.Forms.ListView listView_Hospital; + private System.Windows.Forms.ColumnHeader HospitalName; + private System.Windows.Forms.ColumnHeader FileName; + private System.Windows.Forms.ColumnHeader DefaultPort; + private System.Windows.Forms.ColumnHeader SCPath; + private System.Windows.Forms.ColumnHeader WWWPath; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip_ListView; + private System.Windows.Forms.ToolStripMenuItem tsmi_Insert; + private System.Windows.Forms.ToolStripMenuItem tsmi_Edit; + private System.Windows.Forms.ToolStripMenuItem tsmi_Delete; + private System.Windows.Forms.LinkLabel ll_Sync; + } +} \ No newline at end of file diff --git a/Tiobon.PublishHelper/Frm/Form_Hospital.cs b/Tiobon.PublishHelper/Frm/Form_Hospital.cs new file mode 100644 index 00000000..98fae892 --- /dev/null +++ b/Tiobon.PublishHelper/Frm/Form_Hospital.cs @@ -0,0 +1,188 @@ +using System.Data; + +namespace Tiobon.PublishHelper +{ + public partial class Form_Hospital : Form + { + string devName = string.Empty; + public Form_Hospital(string name) + { + InitializeComponent(); + devName = name; + } + + private void Form_Hospital_Load(object sender, EventArgs e) + { + this.Text = $"医院管理 - {devName}"; + RefreshView(); + } + + private void RefreshView() + { + listView_Hospital.Items.Clear(); + Utility.m_DevServers.Where(o => o.Name == devName).FirstOrDefault() + ?.Hospitals + ?.ForEach(o => + { + ListViewItem item = new ListViewItem(); + item.SubItems[0].Text = o.Name; + item.SubItems.Add(o.FileName); + item.SubItems.Add(o.DefaultFort); + item.SubItems.Add(o.SCPath); + item.SubItems.Add(o.WWWPath); + listView_Hospital.Items.Add(item); + }); + } + + + private void tsmi_Insert_Click(object sender, EventArgs e) + { + using (Form_Hospital_Item f = new Form_Hospital_Item(devName, "新增")) + { + f.ShowDialog(); + } + Utility.SaveDevServer(); + RefreshView(); + } + + private void tsmi_Edit_Click(object sender, EventArgs e) + { + if (this.listView_Hospital.SelectedItems.Count <= 0) + return; + using (Form_Hospital_Item f = new Form_Hospital_Item(devName, $"编辑 - {this.listView_Hospital.SelectedItems[0].Text}")) + { + f.ShowDialog(); + } + Utility.SaveDevServer(); + RefreshView(); + } + + private void tsmi_Delete_Click(object sender, EventArgs e) + { + if (this.listView_Hospital.SelectedItems.Count <= 0) + { + return; + } + if (MessageBox.Show("是否确认删除?", "提示", MessageBoxButtons.YesNo) != DialogResult.Yes) + { + return; + } + var server = Utility.m_DevServers.Where(o => o.Name == devName).FirstOrDefault(); + if (!(server is null)) + { + var item = server.Hospitals.Where(o => o.Name == this.listView_Hospital.SelectedItems[0].Text).FirstOrDefault(); + if (!(item is null)) + { + server.Hospitals.Remove(item); + Utility.SaveDevServer(); + RefreshView(); + } + } + } + + private void ll_Sync_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + var server = Utility.m_DevServers.Where(o => o.Name == devName).FirstOrDefault(); + if (server is null) + return; + if (!Utility.Ping(server.Ip)) + { + MessageBox.Show("网络连接失败!", "提示"); + return; + } + this.Cursor = Cursors.WaitCursor; + bool b_add = false; + try + { + bool b_dev = SftpHelper.Exists(server, $"/home/{server.UserName}/compose"); + var hospitals = SftpHelper.ListDirectory(server, b_dev ? $"/home/{server.UserName}/compose" : $"/home/{server.UserName}").Select(o => o.Name).ToList(); + hospitals.ForEach(hospitalName => + { + if (hospitalName == (b_dev ? "sample" : "tools")) + return; + if (!b_dev) + { + if (!SftpHelper.Exists(server, $"/home/{server.UserName}/{hospitalName}/.env")) + { + Utility.SendLog("同步", $"发现 文件夹 {hospitalName} 不存在 .env 文件,跳过同步"); + return; + } + } + var item = server.Hospitals.Where(o => o.FileName == hospitalName).FirstOrDefault(); + var path = System.Environment.CurrentDirectory.Replace(@"\backend\src\Assistant\JianLian.HDIS.PublishHelper\bin\Debug", ""); + //获取医院信息 + var fname = Utility.GetTempFileName(".env"); + bool b_suc = SftpHelper.DownloadFile(server, b_dev ? $"/home/{server.UserName}/compose/{hospitalName}/.env" : $"/home/{server.UserName}/{hospitalName}/.env", fname); + var content = File.ReadAllText(fname); + var datas = content.Split(new string[] { "\r", "\n", "=" }, StringSplitOptions.RemoveEmptyEntries); + var hospital = new Hospital + { + Name = b_dev ? datas[3] : hospitalName, + FileName = b_dev ? datas[3] : hospitalName, + DefaultFort = datas[1], + SCPath = $"{path}\\backend", + WWWPath = $"" + }; + + if (item is null) + { + if (b_suc) + { + server.Hospitals.Add(hospital); + //新医院 + Utility.SendLog("同步", $"发现新医院 {hospitalName} 端口 {hospital.DefaultFort}"); + b_add = true; + } + } + else + { + //已有医院查看端口是否一致 + if (item.DefaultFort != hospital.DefaultFort) + { + Utility.SendLog("同步", $"医院 {hospitalName} 端口号不一致 {item.DefaultFort},更新为实际端口号 {hospital.DefaultFort}"); + item.DefaultFort = hospital.DefaultFort; + } + else + { + Utility.SendLog("同步", $"医院 {hospitalName} 端口号一致 {hospital.DefaultFort}"); + } + } + }); + + var notExsit = new List(); + server.Hospitals.ForEach(hospital => + { + if (!hospitals.Contains(hospital.FileName)) + { + notExsit.Add(hospital); + } + }); + notExsit.ForEach(hospital => + { + server.Hospitals.Remove(hospital); + //医院不存在 + Utility.SendLog("同步", $"医院已经不存在 {hospital.FileName} 端口 {hospital.DefaultFort}"); + }); + } + catch (Exception ex) + { + Utility.SendLog("同步", $"同步失败:{ex}"); + } + RefreshView(); + Utility.SendLog("同步", $"同步完毕" + (b_add ? "请完善医院信息" : "")); + this.Cursor = Cursors.Default; + } + + private void listView_Hospital_MouseDoubleClick(object sender, MouseEventArgs e) + { + if (this.listView_Hospital.SelectedItems.Count <= 0) + return; + using (Form_Hospital_Item f = new Form_Hospital_Item(devName, $"编辑 - {this.listView_Hospital.SelectedItems[0].Text}")) + { + f.ShowDialog(); + } + Utility.SaveDevServer(); + RefreshView(); + } + } +} diff --git a/Tiobon.PublishHelper/Frm/Form_Hospital.resx b/Tiobon.PublishHelper/Frm/Form_Hospital.resx new file mode 100644 index 00000000..f548663f --- /dev/null +++ b/Tiobon.PublishHelper/Frm/Form_Hospital.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/Tiobon.PublishHelper/Frm/Form_Hospital_Item.Designer.cs b/Tiobon.PublishHelper/Frm/Form_Hospital_Item.Designer.cs new file mode 100644 index 00000000..0a171a0e --- /dev/null +++ b/Tiobon.PublishHelper/Frm/Form_Hospital_Item.Designer.cs @@ -0,0 +1,241 @@ +namespace Tiobon.PublishHelper +{ + partial class Form_Hospital_Item + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.gb_main = new System.Windows.Forms.GroupBox(); + this.lbl_www_default = new System.Windows.Forms.Label(); + this.lbl_sc_default = new System.Windows.Forms.Label(); + this.txt_Port = new System.Windows.Forms.TextBox(); + this.lbl_Port = new System.Windows.Forms.Label(); + this.txt_WWWPath = new System.Windows.Forms.TextBox(); + this.lbl_WWWPath = new System.Windows.Forms.Label(); + this.txt_SCPath = new System.Windows.Forms.TextBox(); + this.lbl_SCPath = new System.Windows.Forms.Label(); + this.txt_FileName = new System.Windows.Forms.TextBox(); + this.lbl_FileName = new System.Windows.Forms.Label(); + this.txt_Name = new System.Windows.Forms.TextBox(); + this.lbl_Name = new System.Windows.Forms.Label(); + this.btn_Ok = new System.Windows.Forms.Button(); + this.btn_Cancel = new System.Windows.Forms.Button(); + this.gb_main.SuspendLayout(); + this.SuspendLayout(); + // + // gb_main + // + this.gb_main.Controls.Add(this.lbl_www_default); + this.gb_main.Controls.Add(this.lbl_sc_default); + this.gb_main.Controls.Add(this.txt_Port); + this.gb_main.Controls.Add(this.lbl_Port); + this.gb_main.Controls.Add(this.txt_WWWPath); + this.gb_main.Controls.Add(this.lbl_WWWPath); + this.gb_main.Controls.Add(this.txt_SCPath); + this.gb_main.Controls.Add(this.lbl_SCPath); + this.gb_main.Controls.Add(this.txt_FileName); + this.gb_main.Controls.Add(this.lbl_FileName); + this.gb_main.Controls.Add(this.txt_Name); + this.gb_main.Controls.Add(this.lbl_Name); + this.gb_main.Location = new System.Drawing.Point(12, 12); + this.gb_main.Name = "gb_main"; + this.gb_main.Size = new System.Drawing.Size(270, 190); + this.gb_main.TabIndex = 0; + this.gb_main.TabStop = false; + // + // lbl_www_default + // + this.lbl_www_default.AutoSize = true; + this.lbl_www_default.ForeColor = System.Drawing.Color.Red; + this.lbl_www_default.Location = new System.Drawing.Point(22, 171); + this.lbl_www_default.Name = "lbl_www_default"; + this.lbl_www_default.Size = new System.Drawing.Size(59, 12); + this.lbl_www_default.TabIndex = 19; + this.lbl_www_default.Text = "(...\\www)"; + // + // lbl_sc_default + // + this.lbl_sc_default.AutoSize = true; + this.lbl_sc_default.ForeColor = System.Drawing.Color.Red; + this.lbl_sc_default.Location = new System.Drawing.Point(22, 137); + this.lbl_sc_default.Name = "lbl_sc_default"; + this.lbl_sc_default.Size = new System.Drawing.Size(53, 12); + this.lbl_sc_default.TabIndex = 18; + this.lbl_sc_default.Text = "(...\\sc)"; + // + // txt_Port + // + this.txt_Port.Location = new System.Drawing.Point(105, 86); + this.txt_Port.Name = "txt_Port"; + this.txt_Port.Size = new System.Drawing.Size(144, 21); + this.txt_Port.TabIndex = 16; + this.txt_Port.Text = "600"; + // + // lbl_Port + // + this.lbl_Port.AutoSize = true; + this.lbl_Port.Location = new System.Drawing.Point(22, 89); + this.lbl_Port.Name = "lbl_Port"; + this.lbl_Port.Size = new System.Drawing.Size(59, 12); + this.lbl_Port.TabIndex = 17; + this.lbl_Port.Text = "默认端口:"; + this.lbl_Port.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // txt_WWWPath + // + this.txt_WWWPath.Location = new System.Drawing.Point(105, 152); + this.txt_WWWPath.Name = "txt_WWWPath"; + this.txt_WWWPath.Size = new System.Drawing.Size(144, 21); + this.txt_WWWPath.TabIndex = 12; + this.txt_WWWPath.Text = "E:\\code\\huhang\\ui\\www"; + // + // lbl_WWWPath + // + this.lbl_WWWPath.AutoSize = true; + this.lbl_WWWPath.Location = new System.Drawing.Point(22, 155); + this.lbl_WWWPath.Name = "lbl_WWWPath"; + this.lbl_WWWPath.Size = new System.Drawing.Size(59, 12); + this.lbl_WWWPath.TabIndex = 13; + this.lbl_WWWPath.Text = "前端路径:"; + this.lbl_WWWPath.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // txt_SCPath + // + this.txt_SCPath.Location = new System.Drawing.Point(105, 119); + this.txt_SCPath.Name = "txt_SCPath"; + this.txt_SCPath.Size = new System.Drawing.Size(144, 21); + this.txt_SCPath.TabIndex = 10; + this.txt_SCPath.Text = "E:\\code\\huhang\\sc"; + // + // lbl_SCPath + // + this.lbl_SCPath.AutoSize = true; + this.lbl_SCPath.Location = new System.Drawing.Point(22, 122); + this.lbl_SCPath.Name = "lbl_SCPath"; + this.lbl_SCPath.Size = new System.Drawing.Size(59, 12); + this.lbl_SCPath.TabIndex = 11; + this.lbl_SCPath.Text = "后端路径:"; + this.lbl_SCPath.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // txt_FileName + // + this.txt_FileName.Location = new System.Drawing.Point(105, 53); + this.txt_FileName.Name = "txt_FileName"; + this.txt_FileName.Size = new System.Drawing.Size(144, 21); + this.txt_FileName.TabIndex = 8; + this.txt_FileName.Text = "yiyou"; + // + // lbl_FileName + // + this.lbl_FileName.AutoSize = true; + this.lbl_FileName.Location = new System.Drawing.Point(22, 56); + this.lbl_FileName.Name = "lbl_FileName"; + this.lbl_FileName.Size = new System.Drawing.Size(71, 12); + this.lbl_FileName.TabIndex = 9; + this.lbl_FileName.Text = "文件夹名称:"; + this.lbl_FileName.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // txt_Name + // + this.txt_Name.Location = new System.Drawing.Point(105, 20); + this.txt_Name.Name = "txt_Name"; + this.txt_Name.Size = new System.Drawing.Size(144, 21); + this.txt_Name.TabIndex = 6; + this.txt_Name.Text = "玉林市第一人民医院"; + // + // lbl_Name + // + this.lbl_Name.AutoSize = true; + this.lbl_Name.Location = new System.Drawing.Point(22, 23); + this.lbl_Name.Name = "lbl_Name"; + this.lbl_Name.Size = new System.Drawing.Size(59, 12); + this.lbl_Name.TabIndex = 7; + this.lbl_Name.Text = "医院名称:"; + this.lbl_Name.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // btn_Ok + // + this.btn_Ok.Location = new System.Drawing.Point(30, 218); + this.btn_Ok.Name = "btn_Ok"; + this.btn_Ok.Size = new System.Drawing.Size(75, 23); + this.btn_Ok.TabIndex = 1; + this.btn_Ok.Text = "确定(&O)"; + this.btn_Ok.UseVisualStyleBackColor = true; + this.btn_Ok.Click += new System.EventHandler(this.btn_Ok_Click); + // + // btn_Cancel + // + this.btn_Cancel.Location = new System.Drawing.Point(177, 218); + this.btn_Cancel.Name = "btn_Cancel"; + this.btn_Cancel.Size = new System.Drawing.Size(75, 23); + this.btn_Cancel.TabIndex = 2; + this.btn_Cancel.Text = "取消(&C)"; + this.btn_Cancel.UseVisualStyleBackColor = true; + this.btn_Cancel.Click += new System.EventHandler(this.btn_Cancel_Click); + // + // Form_Hospital_Item + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(296, 256); + this.Controls.Add(this.btn_Cancel); + this.Controls.Add(this.btn_Ok); + this.Controls.Add(this.gb_main); + this.MaximizeBox = false; + this.MaximumSize = new System.Drawing.Size(312, 295); + this.MinimizeBox = false; + this.MinimumSize = new System.Drawing.Size(312, 295); + this.Name = "Form_Hospital_Item"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "新增"; + this.Load += new System.EventHandler(this.Form_Hospital_Item_Load); + this.gb_main.ResumeLayout(false); + this.gb_main.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox gb_main; + private System.Windows.Forms.TextBox txt_WWWPath; + private System.Windows.Forms.Label lbl_WWWPath; + private System.Windows.Forms.TextBox txt_SCPath; + private System.Windows.Forms.Label lbl_SCPath; + private System.Windows.Forms.TextBox txt_FileName; + private System.Windows.Forms.Label lbl_FileName; + private System.Windows.Forms.TextBox txt_Name; + private System.Windows.Forms.Label lbl_Name; + private System.Windows.Forms.Button btn_Ok; + private System.Windows.Forms.Button btn_Cancel; + private System.Windows.Forms.TextBox txt_Port; + private System.Windows.Forms.Label lbl_Port; + private System.Windows.Forms.Label lbl_www_default; + private System.Windows.Forms.Label lbl_sc_default; + } +} \ No newline at end of file diff --git a/Tiobon.PublishHelper/Frm/Form_Hospital_Item.cs b/Tiobon.PublishHelper/Frm/Form_Hospital_Item.cs new file mode 100644 index 00000000..354c3e46 --- /dev/null +++ b/Tiobon.PublishHelper/Frm/Form_Hospital_Item.cs @@ -0,0 +1,119 @@ +using System.Data; + +namespace Tiobon.PublishHelper +{ + public partial class Form_Hospital_Item : Form + { + bool b_edit = false; + string devName = string.Empty; + Hospital hoipitalOld; + public Hospital m_Hoipital; + public Form_Hospital_Item(string devname, string name) + { + InitializeComponent(); + this.Text = name; + devName = devname; + b_edit = this.Text != "新增"; + var path = System.Environment.CurrentDirectory.Replace(@"\backend\src\Assistant\JianLian.HDIS.PublishHelper\bin\Debug", ""); + this.txt_SCPath.Text = $"{path}\\backend"; + this.txt_WWWPath.Text = $"{path}\\web"; + } + + private void Form_Hospital_Item_Load(object sender, EventArgs e) + { + if (b_edit) + { + hoipitalOld = Utility.m_DevServers + .Where(o => o.Name == devName) + .FirstOrDefault() + ?.Hospitals + ?.Where(o => o.Name == this.Text.Split(new string[] { " - " }, StringSplitOptions.RemoveEmptyEntries)[1]) + .FirstOrDefault(); + if (!(hoipitalOld is null)) + { + this.txt_Name.Text = hoipitalOld.Name; + this.txt_FileName.Text = hoipitalOld.FileName; + this.txt_Port.Text = hoipitalOld.DefaultFort; + this.txt_SCPath.Text = hoipitalOld.SCPath; + this.txt_WWWPath.Text = hoipitalOld.WWWPath; + } + } + } + + private void btn_Ok_Click(object sender, EventArgs e) + { + foreach (var control in gb_main.Controls) + { + if (control is TextBox) + { + var textBox = control as TextBox; + if (string.IsNullOrEmpty(textBox.Text.Trim())) + { + MessageBox.Show($"{textBox.Name},不允许为空!", "提示"); + return; + } + } + } + + int.TryParse(this.txt_Port.Text.Trim(), out int port); + if (port < 100 || port > 655) + { + MessageBox.Show($"端口配置不正确,端口取值范围[100,655]!", "提示"); + return; + } + var server = Utility.m_DevServers.Where(o => o.Name == devName).FirstOrDefault(); + if (server is null) + return; + m_Hoipital = new Hospital + { + Name = this.txt_Name.Text.Trim(), + FileName = this.txt_FileName.Text.Trim(), + DefaultFort = this.txt_Port.Text.Trim(), + SCPath = this.txt_SCPath.Text.Trim(), + WWWPath = this.txt_WWWPath.Text.Trim(), + }; + if (b_edit) + { + server.Hospitals.Remove(hoipitalOld); + } + bool b_suc = false; + try + { + if (server.Hospitals.Any(o => o.Name == this.txt_Name.Text.Trim())) + { + MessageBox.Show($"医院名称已存在!", "提示"); + return; + } + if (server.Hospitals.Any(o => o.FileName == this.txt_FileName.Text.Trim())) + { + MessageBox.Show($"文件夹已存在!", "提示"); + return; + } + if (server.Hospitals.Any(o => o.DefaultFort == this.txt_Port.Text.Trim())) + { + MessageBox.Show($"端口已存在!", "提示"); + return; + } + b_suc = true; + } + finally + { + if (!b_suc) + { + m_Hoipital = null; + if (b_edit) + { + server.Hospitals.Add(hoipitalOld); + } + } + } + server.Hospitals.Add(m_Hoipital); + this.Close(); + } + + private void btn_Cancel_Click(object sender, EventArgs e) + { + this.Close(); + } + } +} diff --git a/Tiobon.PublishHelper/Frm/Form_Hospital_Item.resx b/Tiobon.PublishHelper/Frm/Form_Hospital_Item.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/Tiobon.PublishHelper/Frm/Form_Hospital_Item.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Tiobon.PublishHelper/Program.cs b/Tiobon.PublishHelper/Program.cs new file mode 100644 index 00000000..7bb3b10f --- /dev/null +++ b/Tiobon.PublishHelper/Program.cs @@ -0,0 +1,17 @@ +namespace Tiobon.PublishHelper +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + // To customize application configuration such as set high DPI settings or default font, + // see https://aka.ms/applicationconfiguration. + ApplicationConfiguration.Initialize(); + Application.Run(new Form1()); + } + } +} \ No newline at end of file diff --git a/Tiobon.PublishHelper/Src/CmdHelper.cs b/Tiobon.PublishHelper/Src/CmdHelper.cs new file mode 100644 index 00000000..536ff4d6 --- /dev/null +++ b/Tiobon.PublishHelper/Src/CmdHelper.cs @@ -0,0 +1,84 @@ +using System.Diagnostics; + +namespace Tiobon.PublishHelper +{ + /// + /// CmdHelper + /// + public class CmdHelper + { + /// + /// 指令Cmd命令 + /// + /// + /// + public static (bool, string) ExecCmd(string str) + { + string msg = string.Empty; + bool hasError = false; + bool completed = false; + string cmdCur = string.Empty; + using (Process m_Cmd = new Process()) + { + m_Cmd.StartInfo.FileName = "cmd.exe"; + m_Cmd.StartInfo.WorkingDirectory = "."; + m_Cmd.StartInfo.UseShellExecute = false; + m_Cmd.StartInfo.RedirectStandardInput = true; + m_Cmd.StartInfo.RedirectStandardOutput = true; + m_Cmd.StartInfo.CreateNoWindow = true; + m_Cmd.OutputDataReceived += new DataReceivedEventHandler((sender, e) => + { + if (!string.IsNullOrEmpty(e.Data)) + { + var res = e.Data; + if (res.Contains("\u001b")) + { + foreach (System.Text.RegularExpressions.Match item in Utility.m_RegexUb.Matches(res)) + { + res = res.Replace(item.Value, ""); + } + } + Utility.SendLog("", res); + if (res.Trim() != "Unable to use package assets cache due to I/O error. This can occur when the same project is built more than once in parallel. Performance may be degraded, but the build result will not be impacted." + && (res.Contains("ERR!") || res.Contains("ERROR") || res.Contains("error"))) + { + msg = res; + hasError = true; + } + + if (res.EndsWith("exit")) + { + completed = true; + } + } + }); + m_Cmd.Start(); + m_Cmd.BeginOutputReadLine(); + + str.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) + .ToList() + .ForEach(s => + { + if (hasError) + return; + cmdCur = s; + m_Cmd.StandardInput.WriteLine(cmdCur); + }); + + int timecout = 60 * 15; + while (!completed && !hasError) + { + System.Threading.Thread.Sleep(1000); + if (--timecout < 0) + { + msg = $"指令执行超时:{str}"; + hasError = true; + break; + } + } + } + return (hasError, msg); + } + + } +} diff --git a/Tiobon.PublishHelper/Src/DevServer.cs b/Tiobon.PublishHelper/Src/DevServer.cs new file mode 100644 index 00000000..d1effb7b --- /dev/null +++ b/Tiobon.PublishHelper/Src/DevServer.cs @@ -0,0 +1,72 @@ +namespace Tiobon.PublishHelper; + +/// +/// 服务器 +/// +[Serializable] +public class Server +{ + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// Ip + /// + public string Ip { get; set; } + /// + /// 用户名 + /// + public string UserName { get; set; } + /// + /// 密码 + /// + public string Password { get; set; } + /// + /// Su密码 + /// + public string SuPassword { get; set; } + /// + /// 端口 + /// + public int Port { get; set; } +} +/// +/// 开发服务器 +/// +[Serializable] +public class DevServer : Server +{ + /// + /// 医院信息 + /// + public List Hospitals { get; set; } +} + +/// +/// 医院 +/// +[Serializable] +public class Hospital +{ + /// + /// 医院名称 + /// + public string Name { get; set; } + /// + /// 文件夹名称 + /// + public string FileName { get; set; } + /// + /// 默认端口前三位 + /// + public string DefaultFort { get; set; } + /// + /// 本地后端代码路径 + /// + public string SCPath { get; set; } + /// + /// 本地前端代码路径 + /// + public string WWWPath { get; set; } +} diff --git a/Tiobon.PublishHelper/Src/DockerCommand.cs b/Tiobon.PublishHelper/Src/DockerCommand.cs new file mode 100644 index 00000000..50759223 --- /dev/null +++ b/Tiobon.PublishHelper/Src/DockerCommand.cs @@ -0,0 +1,105 @@ +namespace Tiobon.PublishHelper +{ + /// + /// Docker命令封装 + /// + public class DockerCommand + { + /// + /// docker ps + /// + /// + /// + public static string GetDockerStatus(string hospital) + { + return $"sudo docker ps -a --format \"table {{{{.ID}}}}||{{{{.Names}}}}||{{{{.Image}}}}||{{{{.Command}}}}||{{{{.CreatedAt}}}}||{{{{.RunningFor}}}}||{{{{.Ports}}}}||{{{{.Status}}}}||{{{{.Networks}}}}\" | grep \"{hospital}_\""; + } + /// + /// docker containerName + /// + /// + /// + /// + public static string GetDockerContainerName(string hospital, string modelName) + { + return $"sudo docker ps -a --format \"table {{{{.Names}}}}\" | grep \"{hospital}_{modelName}\""; + } + /// + /// docker logs + /// + /// + /// + public static string GetDockerLogs(string containerName) + { + return $"sudo docker logs {containerName} --tail=50"; + } + /// + /// docker-compose down + /// + /// + /// + /// + public static string DockerComposeDown(string userName, string hospital, string suffix ) + { + return $"cd /home/{userName}/ihdis{suffix}/{hospital};sudo docker-compose down"; + } + /// + /// docker-compose up + /// + /// + /// + /// + public static string DockerComposeUp(string userName, string hospital, string suffix ) + { + return $"cd /home/{userName}/ihdis{suffix}/{hospital};sudo docker-compose up -d"; + } + /// + /// docker-compose restart + /// + /// + /// + /// + public static string DockerComposeRestart(string userName, string hospital, string suffix ) + { + return $"cd /home/{userName}/ihdis{suffix}/{hospital};sudo docker-compose restart"; + } + /// + /// docker-compose remove + /// + /// + /// + /// + public static string DockerComposeRemove(string userName, string hospital, string cname, string suffix ) + { + return $"cd /home/{userName}/ihdis{suffix}/{hospital};sudo docker-compose stop {cname};sudo docker-compose rm -f {cname}"; + } + /// + /// docker container restart + /// + /// + /// + public static string DockeContainerRestart(string containerId) + { + return $"sudo docker restart {containerId}"; + } + /// + /// docker-compose restart container + /// + /// + /// + /// + public static string DockerComposeContainerRestart(string userName, string hospital, string container, string suffix ) + { + return $"cd /home/{userName}/ihdis{suffix}/{hospital};sudo docker-compose restart {container}"; + } + /// + /// docker container log + /// + /// + /// + public static string DockeContainerLog(string userName, string hospital, string container, string suffix ) + { + return $"cd /home/{userName}/ihdis{suffix}/{hospital};sudo docker-compose logs {container}"; + } + } +} diff --git a/Tiobon.PublishHelper/Src/OprateLog.cs b/Tiobon.PublishHelper/Src/OprateLog.cs new file mode 100644 index 00000000..0979f33f --- /dev/null +++ b/Tiobon.PublishHelper/Src/OprateLog.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tiobon.PublishHelper +{ + /// + /// 操作记录 + /// + [Serializable] + public class OprateLog + { + /// + /// 上一次选择的服务器 + /// + public string ServerName { get; set; } + /// + /// 上一次选择的医院 + /// + public string HospitalName { get; set; } + /// + /// webapi + /// + public bool Webapi { get; set; } + /// + /// hfs + /// + public bool Hfs { get; set; } + /// + /// rtm + /// + public bool Rtm { get; set; } + /// + /// job + /// + public bool Job { get; set; } + /// + /// web + /// + public bool Web { get; set; } + /// + /// pad + /// + public bool Pad { get; set; } + /// + /// remove + /// + public bool Remove { get; set; } + /// + /// build + /// + public bool Build { get; set; } + + /// + /// 版本打包-开发服务器 + /// + public string PackDevIp { get; set; } + /// + /// 版本打包-医院 + /// + public string PackHospital { get; set; } + /// + /// 版本打包-发布服务器 + /// + public string PackPublishIp { get; set; } + /// + /// 版本打包-版本 + /// + public string PackVersion { get; set; } + /// + /// 版本打包-数据库脚本 + /// + public bool PackDbFile { get; set; } + /// + /// 版本打包-打包前先执行发布 + /// + public bool PackPublish { get; set; } + /// + /// 版本打包-Git + /// + public bool PackGit { get; set; } + /// + /// 版本打包-是否自动下载 + /// + public bool PackDownload { get; set; } + /// + /// 版本打包-是否为升级包 + /// + public bool PackUpgrade { get; set; } + /// + /// 版本打包-TS升级包 + /// + public bool PackUpgradeTS { get; set; } + /// + /// 版本打包-TS升级包项目名称 + /// + public string PackUpgradeTSCustom { get; set; } + /// + /// TS插件打包-项目地址 + /// + public string TSPath { get; set; } + /// + /// TS插件打包-版本号 + /// + public string TSVersion { get; set; } + /// + /// TS插件打包-保存位置 + /// + public string TSSavePath { get; set; } + /// + /// TS插件打包-是否自定义 + /// + public bool TSCustom { get; set; } + /// + /// TS插件打包-是否编译 + /// + public bool TSBuild { get; set; } + /// + /// TS插件打包-自定义医院 + /// + public string TSCustomHospitals { get; set; } + } +} diff --git a/Tiobon.PublishHelper/Src/PublishServer.cs b/Tiobon.PublishHelper/Src/PublishServer.cs new file mode 100644 index 00000000..3ed42f6a --- /dev/null +++ b/Tiobon.PublishHelper/Src/PublishServer.cs @@ -0,0 +1,79 @@ +namespace Tiobon.PublishHelper +{ + + /// + /// 发布服务器 + /// + [Serializable] + public class PublishServer : Server + { + private List folders; + /// + /// 版本文件夹 + /// + public List Folders + { + get { return folders; } + set + { + if (folders == null) + value = new List(); + folders = value; + } + } + } + + /// + /// 版本文件夹 + /// + [Serializable] + public class VersionFolder + { + /// + /// 文件名称 + /// + public string FolderName { get; set; } + /// + /// 创建时间 + /// + public DateTime CreateTime { get; set; } + /// + /// 文件大小 + /// + public long Size { get; set; } + + private List files; + /// + /// 版本文件 + /// + public List Files + { + get { return files; } + set + { + if (files == null) + value = new List(); + files = value; + } + } + } + /// + /// 版本文件 + /// + [Serializable] + public class VersionFile + { + /// + /// 文件名称 + /// + public string FileName { get; set; } + /// + /// 创建时间 + /// + public DateTime CreateTime { get; set; } + /// + /// 文件大小 + /// + public long Size { get; set; } + } +} diff --git a/Tiobon.PublishHelper/Src/SftpHelper.cs b/Tiobon.PublishHelper/Src/SftpHelper.cs new file mode 100644 index 00000000..b9d97a2a --- /dev/null +++ b/Tiobon.PublishHelper/Src/SftpHelper.cs @@ -0,0 +1,503 @@ +using System.Net; +using System.Text; +using FluentFTP; +using Renci.SshNet; +using Renci.SshNet.Sftp; + +namespace Tiobon.PublishHelper +{ + /// + /// SFTP操作类 + /// + public class SftpHelper + { + #region 下载文件 + /// + /// 下载单个文件 + /// + /// + /// + /// + /// + /// + public static bool DownloadFile(Server server, string remoteFile, string localFile, bool b_log = false, Action progress = null, Action completedAction = null) + { + bool b_suc = false; + try + { + if (!Utility.Ping(server.Ip, b_log)) + { + return b_suc; + } + using (SftpClient sftp = new SftpClient(server.Ip, server.Port, "root", server.SuPassword)) + { + sftp.Connect(); + if (sftp.Exists(remoteFile)) + { + if (b_log) + Utility.SendLog("下载", $"下载文件 {remoteFile}"); + if (File.Exists(localFile)) + { + File.Delete(localFile); + System.Threading.Thread.Sleep(50); + } + var sftFile = sftp.ListDirectory(remoteFile.Substring(0, remoteFile.LastIndexOf('/'))).Where(o => o.FullName == remoteFile).FirstOrDefault(); + using (var file = File.OpenWrite(localFile)) + { + sftp.DownloadFile(remoteFile, file, pro => + { + progress?.Invoke(sftFile.Length, pro); + }); + if (b_log) + Utility.SendLog("下载", $"成功 {remoteFile} =>> {localFile} len {file.Length} byte"); + b_suc = true; + } + } + else + { + if (b_log) + Utility.SendLog("下载", $"文件不存在 {remoteFile}"); + } + } + } + catch (Exception ex) + { + if (b_log) + Utility.SendLog("下载", $"下载文件失败:{remoteFile} {ex.Message}"); + } + finally + { + completedAction?.Invoke(); + } + return b_suc; + } + #endregion + + #region 上传文件 + /// + /// 上传单个文件 + /// + /// + /// + /// + /// + public static void UploadFile(Server server, string localFile, string remoteFile, Action progress = null, bool create = false) + { + if (!Utility.Ping(server.Ip)) + return; + + try + { + FtpClient client = new FtpClient(); + client.Host = server.Ip; + client.Port = server.Port; + client.Credentials = new NetworkCredential(server.UserName, server.SuPassword); + client.AutoConnect(); + + using (var file = File.OpenRead(localFile)) + { + try + { + var len = file.Length; + client.UploadFile(localFile, remoteFile); + Utility.SendLog("上传", $"成功 {localFile} =>> {remoteFile} len {len} byte"); + } + catch (Exception e) + { + Utility.SendLog("上传", $"失败 {remoteFile} 原因:{e}"); + } + } + client.Disconnect(); + } + catch (Exception E) + { + Utility.SendLog("上传", $"失败 {remoteFile} 原因:{E}"); + } + + #region 作废代码 + //using (SftpClient sftp = new SftpClient(server.Ip, server.Port, server.UserName, server.SuPassword)) + //{ + // sftp.Connect(); + // using (var file = File.OpenRead(localFile)) + // { + // try + // { + // if (!sftp.Exists(remoteFile) && create) + // { + // sftp.Create(remoteFile); + // } + // var len = file.Length; + // sftp.UploadFile(file, remoteFile, pro => + // { + // progress?.Invoke(len, pro); + // }); + // Utility.SendLog("上传", $"成功 {localFile} =>> {remoteFile} len {len} byte"); + // } + // catch (Exception e) + // { + // Utility.SendLog("上传", $"失败 {remoteFile} 原因:{e}"); + // } + // } + //} + #endregion + } + /// + /// 批量上传文件 + /// + /// + /// + /// + /// + /// + public static void UploadFile(Server server, string localPath, string remotePath, List files, Action progress) + { + if (!Utility.Ping(server.Ip)) + return; + + try + { + progress(files.Count, 0); + + FtpClient sftp = new FtpClient(); + sftp.Host = server.Ip; + sftp.Port = server.Port; + sftp.Credentials = new NetworkCredential(server.UserName, server.SuPassword); + sftp.AutoConnect(); + + var count = files.Count; + var index = 0; + files?.ForEach(fname => + { + if (Utility.m_StopPublish) + return; + var localFileName = $"{localPath}\\{fname}"; + var remoteFileName = $"{remotePath}/{fname.Replace("\\", "/")}"; + using (var file = File.OpenRead(localFileName)) + { + var len = file.Length; + try + { + index++; + if (fname.Contains("\\")) + { + StringBuilder sb = new StringBuilder(); + var ff = fname.Substring(0, fname.LastIndexOf("\\")).Split(new string[] { "\\" }, StringSplitOptions.RemoveEmptyEntries); + ff.ToList().ForEach(f => + { + sb.Append($"/{f}"); + var fpath = $"{remotePath}{sb}"; + if (!sftp.DirectoryExists(fpath)) + { + sftp.CreateDirectory(fpath); + Utility.SendLog("上传", $"创建目录成功 {fpath}"); + } + }); + } + //sftp.UploadFile(file, remoteFileName); + sftp.UploadFile(localFileName, remoteFileName); + progress(count, index); + Utility.SendLog("上传", $"[{index}/{count}]成功 {localPath}\\{fname} =>> {remoteFileName} len {len} byte"); + } + catch (Exception e) + { + Utility.SendLog("上传", $"[{index}/{count}] 失败 原因:{fname} {e}"); + try + { + Utility.SendLog("重新上传", $"[{index}/{count}] {fname} "); + sftp.UploadFile(localFileName, remoteFileName); + progress(count, index); + Utility.SendLog("上传", $"[{index}/{count}]成功 {localPath}\\{fname} =>> {remoteFileName} len {len} byte"); + } + catch (Exception E) + { + Utility.SendLog("上传", $"[{index}/{count}] 失败 原因:{fname} {E}"); + + } + } + } + + }); + sftp.Disconnect(); + + #region 作废代码 + //using (SftpClient sftp = new SftpClient(server.Ip, server.Port, "root", server.SuPassword)) + //{ + // sftp.Connect(); + // var count = files.Count; + // var index = 0; + // files?.ForEach(fname => + // { + // if (Utility.m_StopPublish) + // return; + // var localFileName = $"{localPath}\\{fname}"; + // var remoteFileName = $"{remotePath}/{fname.Replace("\\", "/")}"; + // using (var file = File.OpenRead(localFileName)) + // { + // try + // { + // index++; + // var len = file.Length; + // if (fname.Contains("\\")) + // { + // StringBuilder sb = new StringBuilder(); + // var ff = fname.Substring(0, fname.LastIndexOf("\\")).Split(new string[] { "\\" }, StringSplitOptions.RemoveEmptyEntries); + // ff.ToList().ForEach(f => + // { + // sb.Append($"/{f}"); + // var fpath = $"{remotePath}{sb}"; + // if (!sftp.Exists(fpath)) + // { + // sftp.CreateDirectory(fpath); + // Utility.SendLog("上传", $"创建目录成功 {fpath}"); + // } + // }); + // } + // sftp.UploadFile(file, remoteFileName); + // progress(count, index); + // Utility.SendLog("上传", $"[{index}/{count}]成功 {localPath}\\{fname} =>> {remoteFileName} len {len} byte"); + // } + // catch (Exception e) + // { + // Utility.SendLog("上传", $"[{index}/{count}] 失败 原因:{fname} {e}"); + // } + // } + + // }); + //} + #endregion + } + catch (Exception ex) + { + Utility.SendLog("", ex.ToString()); + } + } + #endregion + + #region 获取文件 + /// + /// 获取当前目录的文件列表 + /// + /// + /// + /// + public static List ListFiles(Server server, string remotePath) + { + List list = new List(); + //try + //{ + // using (SftpClient sftp = new SftpClient(server.Ip, server.Port, "root", server.SuPassword)) + // { + // sftp.Connect(); + // list = sftp.ListDirectory(remotePath).Where(f => f.IsRegularFile).ToList(); + // } + //} + //catch (Exception ex) + //{ + // Utility.SendLog("", $"获取文件夹失败:{remotePath} {ex.Message}"); + //} + return list; + } + + public static List GetListing(Server server, string remotePath) + { + FtpClient sftp = new FtpClient(); + sftp.Host = server.Ip; + sftp.Port = server.Port; + sftp.Credentials = new NetworkCredential(server.UserName, server.SuPassword); + sftp.AutoConnect(); + + List list = new List(); + try + { + foreach (FtpListItem item in sftp.GetListing(remotePath)) + { + list.Add(item); + // if this is a file + //if (item.Type == FtpFileSystemObjectType.File) + //{ + + // // get the file size + // long size = sftp.GetFileSize(item.FullName); + + // // calculate a hash for the file on the server side (default algorithm) + // FtpHash hash = sftp.GetChecksum(item.FullName); + //} + + //// get modified date/time of the file or folder + //DateTime time = sftp.GetModifiedTime(item.FullName); + } + sftp.Disconnect(); + } + catch (Exception ex) + { + Utility.SendLog("", $"获取文件夹失败:{remotePath} {ex.Message}"); + } + return list; + } + #endregion + + #region 获取文件夹 + /// + /// 获取当前目录的文件夹列表 + /// + /// + /// + /// + public static List ListDirectory(Server server, string remotePath) + { + List list = new List(); + try + { + FtpClient sftp = new FtpClient(); + sftp.Host = server.Ip; + sftp.Port = server.Port; + sftp.Credentials = new NetworkCredential(server.UserName, server.SuPassword); + sftp.AutoConnect(); + sftp.GetListing(); + + //using (SftpClient sftp = new SftpClient(server.Ip, server.Port, "root", server.SuPassword)) + //{ + // sftp.Connect(); + // list = sftp.ListDirectory(remotePath).Where(f => f.IsDirectory && f.Name != "." && f.Name != "..").ToList(); + //} + } + catch (Exception ex) + { + Utility.SendLog("", $"获取文件夹失败:{remotePath} {ex.Message}"); + } + return list; + } + #endregion + + #region 文件/文件夹是否存在 + /// + /// 文件/文件夹是否存在 + /// + /// + /// + /// + /// + public static bool Exists(Server server, string path) + { + bool b_suc = false; + if (!Utility.Ping(server.Ip)) + { + return b_suc; + } + try + { + //using (SftpClient sftp = new SftpClient(server.Ip, server.Port, "root", server.SuPassword)) + //{ + // sftp.Connect(); + // b_suc = sftp.Exists(path); + //} + } + catch (Exception ex) + { + Utility.SendLog("", ex.ToString()); + } + return b_suc; + } + + public static void CreateDirectory(Server server, string path) + { + if (!Utility.Ping(server.Ip)) + { + return; + } + try + { + using (SftpClient sftp = new SftpClient(server.Ip, server.Port, "root", server.SuPassword)) + { + sftp.Connect(); + if (!sftp.Exists(path)) + { + sftp.CreateDirectory(path); + } + } + } + catch (Exception ex) + { + Utility.SendLog("", ex.ToString()); + } + } + #endregion + + #region 删除文件 + /// + /// 删除文件 + /// + /// + /// + /// + public static bool Delete(Server server, string path) + { + bool b_suc = false; + if (!Utility.Ping(server.Ip)) + return b_suc; + + try + { + FtpClient sftp = new FtpClient(); + sftp.Host = server.Ip; + sftp.Port = server.Port; + sftp.Credentials = new NetworkCredential(server.UserName, server.SuPassword); + sftp.AutoConnect(); + + //using (SftpClient sftp = new SftpClient(server.Ip, server.Port, "root", server.SuPassword)) + //{ + // sftp.Connect(); + // if (sftp.FileExists(path)) + // sftp.Delete(path); + // b_suc = true; + //} + } + catch (Exception ex) + { + Utility.SendLog("", ex.ToString()); + } + return b_suc; + } + #endregion + + #region 删除文件夹 + /// + /// 删除文件夹 + /// + /// + /// + /// + public static bool DeleteDirectory(Server server, string path) + { + bool b_suc = false; + if (!Utility.Ping(server.Ip)) + return b_suc; + + try + { + FtpClient sftp = new FtpClient(); + sftp.Host = server.Ip; + sftp.Port = server.Port; + sftp.Credentials = new NetworkCredential(server.UserName, server.SuPassword); + sftp.AutoConnect(); + if (sftp.DirectoryExists(path)) + sftp.DeleteDirectory(path); + sftp.Disconnect(); + + //using (SftpClient sftp = new SftpClient(server.Ip, server.Port, "root", server.SuPassword)) + //{ + // sftp.Connect(); + // if (sftp.FileExists(path)) + // sftp.Delete(path); + // b_suc = true; + //} + } + catch (Exception ex) + { + Utility.SendLog("", ex.ToString()); + } + return b_suc; + } + #endregion + } +} diff --git a/Tiobon.PublishHelper/Src/SshHelper.cs b/Tiobon.PublishHelper/Src/SshHelper.cs new file mode 100644 index 00000000..ad87a93c --- /dev/null +++ b/Tiobon.PublishHelper/Src/SshHelper.cs @@ -0,0 +1,249 @@ +using Renci.SshNet; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tiobon.PublishHelper +{ + /// + /// SSHHelper + /// + public class SshHelper + { + #region 执行命令 + /// + /// SSH执行命令返回结果 + /// + /// 服务器 + /// 命令 + /// 执行结果 + /// 打印日志 + /// + public static (bool Success, string Result) ExcuteCmd(Server server, string command, bool b_log = false) + { + bool b_suc = false; + string result = string.Empty; + try + { + //if (!Utility.Ping(server.Ip, b_log)) + //{ + // return (b_suc, result); + //} + + using (SshClient ssh = new SshClient(server.Ip, server.Port, "root", server.SuPassword)) + { + ssh.Connect(); + if (b_log) + { + Utility.SendLog(command); + } + var cmd = ssh.RunCommand(command); + if (cmd.ExitStatus != 0) + { + result = cmd.Error; + } + else + { + b_suc = true; + result = $"{cmd.Result}{cmd.Error}"; + } + } + } + catch (Exception ex) + { + result = ex.Message; + } + if (b_log) + { + if (!string.IsNullOrEmpty(result)) + { + result + .Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries) + .ToList() + .ForEach( + s => + { + if (!string.IsNullOrEmpty(s.Trim())) + Utility.SendLog(s); + }); + } + else + { + Utility.SendLog("success"); + } + } + return (b_suc, result); + } + + /// + /// SSH执行批量命令 + /// + /// 服务器 + /// 命令 + /// 日志标识 + /// 完成以后的操作 + public static void ExcuteCmds(Server server, List commands, string logFlag, Action completedAction = null) + { + string result = string.Empty; + try + { + Utility.SetProgressBarVisible(true); + Utility.SendLog(logFlag, "开始执行批量指令", true); + if (!Utility.Ping(server.Ip)) + { + return; + } + + using (SshClient ssh = new SshClient(server.Ip, server.Port, "root", server.SuPassword)) + { + ssh.Connect(); + int index = 0; + if (commands != null) + { + Utility.SetProgressBarValue(commands.Count, 0); + commands.ForEach(command => + { + Utility.SendLog(logFlag, $"{command}"); + var cmd = ssh.RunCommand(command); + if (cmd.ExitStatus != 0) + { + result = cmd.Error; + } + else + { + result = $"{cmd.Result}{cmd.Error}"; + } + if (!string.IsNullOrEmpty(result)) + { + result + .Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries) + .ToList() + .ForEach( + s => + { + if (!string.IsNullOrEmpty(s.Trim())) + Utility.SendLog(logFlag, s); + }); + } + else + { + Utility.SendLog(logFlag, "success"); + } + Utility.SetProgressBarValue(commands.Count, (ulong)++index); + }); + } + } + completedAction?.Invoke(); + } + catch (Exception ex) + { + Utility.SendLog(logFlag, $"{ex.Message}"); + } + Utility.SetProgressBarVisible(false); + Utility.SendLog(logFlag, "执行批量指令完毕", true); + } + #endregion + + #region 执行命令实时返回结果 + public static bool m_InRtm = false; + private static object m_LockRtm = new object(); + /// + /// 执行命令实时返回结果 + /// + /// + /// + public static void ExcuteCmdRtm(Server server, string command) + { + lock (m_LockRtm) + { + if (m_InRtm) + { + Utility.SendLog("执行脚本", $"正在执行其他命令,请等待"); + return; + } + else + { + m_InRtm = true; + } + } + try + { + if (!Utility.Ping(server.Ip)) + { + return; + } + using (var client = new SshClient(server.Ip, server.Port, "root", server.SuPassword)) + { + client.Connect(); + Utility.SendLog("登录", $"[{server.Ip}]成功"); + using (var stream = client.CreateShellStream("anything", 80, 24, 800, 600, 4096)) + { + byte[] buffer = new byte[1000]; + stream.WriteLine("pwd"); + + stream.BeginRead(buffer, 0, buffer.Length, null, null); + + bool end = false; + stream.DataReceived += new EventHandler( + (o, ex) => + { + var str = stream.Read(); + if (str.Contains("\u001b")) + { + foreach (System.Text.RegularExpressions.Match item in Utility.m_RegexUb.Matches(str)) + { + str = str.Replace(item.Value, ""); + } + } + str + .Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries) + .ToList() + .ForEach( + s => + { + if (!string.IsNullOrEmpty(s.Trim())) + Utility.SendLog("", s); + }); + end = str.Trim().EndsWith($"eucloud']#"); + } + ); + command = $"{command};cd /home/{server.UserName};".Replace(";;", ";"); + Utility.SendLog("执行脚本", $"{command}"); + stream.WriteLine(command); + int timecout = 5 * 60; + while (!end) + { + System.Threading.Thread.Sleep(1000); + if (--timecout < 0) + break; + } + Utility.SendLog("执行脚本", $"[{server.Ip}]完毕"); + } + } + } + catch (Exception ex) + { + Utility.SendLog("执行脚本", $"{ex}"); + } + finally + { + lock (m_LockRtm) + { + m_InRtm = false; + } + } + } + + /// + /// 是否繁忙 + /// + /// + public static bool InRtmNow() + { + return m_InRtm; + } + #endregion + } +} diff --git a/Tiobon.PublishHelper/Src/Utility.cs b/Tiobon.PublishHelper/Src/Utility.cs new file mode 100644 index 00000000..e2edb5dc --- /dev/null +++ b/Tiobon.PublishHelper/Src/Utility.cs @@ -0,0 +1,610 @@ +using System.Net; +using System.Net.NetworkInformation; +using System.Text; +using System.Text.RegularExpressions; +using ProtoBuf; + +namespace Tiobon.PublishHelper +{ + /// + /// 辅助类 + /// + public class Utility + { + #region 参数 + /// + /// 停止发布 + /// + public static bool m_StopPublish = false; + /// + /// 替换控制指令 + /// + public static System.Text.RegularExpressions.Regex m_RegexUb = new System.Text.RegularExpressions.Regex(@"\u001b\[\d+[A-z]"); + /// + /// 测试服务器 + /// + public static string m_TestServerIp = "192.168.8.60"; + #endregion + + #region 事件 + /// + /// 记录日志 + /// + public static Action SendLogHandle; + public static void SendLog(string msg, bool status = false) + { + SendLogHandle("", msg); + if (status) + { + SetStatus(msg); + } + lock (m_Logs) + m_Logs.Add(msg); + } + public static void SendLog(string oprate, string msg, bool status = false) + { + SendLogHandle(oprate, msg); + if (status) + { + SetStatus(msg); + } + lock (m_Logs) + { + if (string.IsNullOrEmpty(oprate)) + m_Logs.Add($"{msg}"); + else + m_Logs.Add($"[{oprate}] {msg}"); + } + } + /// + /// 设置进度条显示/隐藏 + /// + public static Action SetProgressBarVisible; + /// + /// 设置进度条状态 + /// + public static Action SetProgressBarValue; + /// + /// 设置当前状态 + /// + public static Action SetStatus; + #endregion + + #region 初始化 + public static void Init() + { + ReadDevServer(); + ReadPublishServer(); + ReadOprateLog(); + Thread log = new Thread(WriteLogger); + log.Start(); + } + #endregion + + #region 服务器管理 + /// + /// 开发服务器列表 + /// + public static List m_DevServers = new List(); + /// + /// 保存开发服务器配置 + /// + public static void SaveDevServer() + { + try + { + string fname = AppDomain.CurrentDomain.BaseDirectory + "\\DevServers.dat"; + if (File.Exists(fname)) + File.Delete(fname); + + using (FileStream fs = new FileStream(fname, FileMode.Create)) + { + Serializer.Serialize(fs, m_DevServers); + } + } + catch { } + } + + /// + /// 读取开发服务器配置 + /// + public static void ReadDevServer() + { + try + { + string fname = AppDomain.CurrentDomain.BaseDirectory + "\\DevServers.dat"; + if (File.Exists(fname)) + using (FileStream fs = new FileStream(fname, FileMode.Open)) + { + m_DevServers = Serializer.Deserialize>(fs); + } + } + catch { } + + if (m_DevServers is null) + m_DevServers = new List(); + + m_DevServers.ForEach(s => + { + if (s.Hospitals is null) + { + s.Hospitals = new List(); + } + }); + } + /// + /// 发布服务器列表 + /// + public static List m_PublishServers = new List(); + /// + /// 保存发布服务器配置 + /// + public static void SavePublishServer() + { + try + { + string fname = AppDomain.CurrentDomain.BaseDirectory + "\\PublishServers.dat"; + if (File.Exists(fname)) + File.Delete(fname); + + using (FileStream fs = new FileStream(fname, FileMode.Create)) + { + Serializer.Serialize(fs, m_DevServers); + } + } + catch { } + } + + /// + /// 读取发布服务器配置 + /// + public static void ReadPublishServer() + { + try + { + string fname = AppDomain.CurrentDomain.BaseDirectory + "\\PublishServers.dat"; + if (File.Exists(fname)) + { + using (FileStream fs = new FileStream(fname, FileMode.Open)) + { + m_PublishServers = Serializer.Deserialize>(fs); + } + } + } + catch { } + + if (m_PublishServers is null) + { + m_PublishServers = new List(); + } + + m_PublishServers.ForEach(s => + { + if (s.Folders is null) + s.Folders = new List(); + + s.Folders.ForEach(f => + { + if (f.Files is null) + f.Files = new List(); + }); + }); + } + #endregion + + #region 操作记录 + /// + /// 操作记录 + /// + public static OprateLog m_OprateLog = new OprateLog(); + /// + /// 保存操作记录 + /// + public static void SaveOprateLog() + { + try + { + string fname = AppDomain.CurrentDomain.BaseDirectory + "\\OprateLog.dat"; + if (File.Exists(fname)) + File.Delete(fname); + + using (FileStream fs = new FileStream(fname, FileMode.Create)) + { + Serializer.Serialize(fs, m_OprateLog); + } + } + catch { } + } + + /// + /// 读取操作记录 + /// + public static void ReadOprateLog() + { + try + { + string fname = AppDomain.CurrentDomain.BaseDirectory + "\\OprateLog.dat"; + if (File.Exists(fname)) + { + using (FileStream fs = new FileStream(fname, FileMode.Open)) + { + m_OprateLog = Serializer.Deserialize(fs); + } + } + } + catch { } + + if (m_OprateLog is null) + { + m_OprateLog = new OprateLog(); + } + } + #endregion + + #region Ping测试 + /// + /// Ping测试 + /// + /// + /// + /// + public static bool Ping(string ip, bool b_log = true) + { + bool b_suc = false; + try + { + using (Ping ping = new Ping()) + { + b_suc = ping.Send(ip, 2000).Status == IPStatus.Success; + } + } + catch + { + b_suc = false; + } + if (!b_suc && b_log) + { + SendLog(ip, "ping失败,不继续执行其他远程操作指令"); + } + return b_suc; + } + #endregion + + #region 获取临时文件名 + /// + /// 获取临时文件名 + /// + /// + /// + /// + public static string GetTempFileName(string fname, bool random = true) + { + return $"{System.Environment.GetEnvironmentVariable("TEMP")}\\{fname}" + (random ? $"_{DateTime.Now.Ticks}" : ""); + } + #endregion + + #region 获取服务器状态 + /// + /// 获取服务器状态 + /// + /// + /// + public static (bool Success, double Cpu, double MemTotal, double MemUsed, double Disk) GetServerStatus(Server server) + { + var res = (false, 0, 0, 0, 0); + try + { + var (Success, Result) = SshHelper.ExcuteCmd(server, "cpu=`top -b -n 1 | awk 'NR>7{sum+=$9} END {print sum}'`\n mem=`free -m | awk 'NR==2{print $2,$3}'` \n disk=`df -h | grep \"home\" |awk '{{print $5}}'` \n echo \"$cpu,$mem,$disk\"", false); + if (Success) + { + //87,7981 4369,96% + var empties = Result.Trim('\n').Trim().Split(new string[] { "%", ",", " " }, StringSplitOptions.RemoveEmptyEntries); + if (empties.Length == 4) + { + return (true, double.Parse(empties[0]), double.Parse(empties[1]), double.Parse(empties[2]), double.Parse(empties[3])); + } + } + } + catch + { } + return res; + } + #endregion + + #region 日志 + /// + /// 停止记录日志 + /// + public static bool m_LogRun = true; + private static List m_Logs = new List(); + /// + /// 日志线程 + /// + private static void WriteLogger() + { + var path = AppDomain.CurrentDomain.BaseDirectory + "Log\\"; + if (!Directory.Exists(path)) + Directory.CreateDirectory(path); + string fname = string.Empty; + var logs = new List(); + while (m_LogRun) + { + try + { + lock (m_Logs) + { + if (m_Logs.Count > 0) + { + m_Logs.ForEach(s => logs.Add(s)); + fname = path + DateTime.Now.ToString("yyyy_MM_dd") + ".txt"; + m_Logs.Clear(); + } + } + if (logs.Count > 0) + { + WriteLoggerToFile(fname, logs); + logs.Clear(); + } + } + catch + { + // ignored + } + finally + { + System.Threading.Thread.Sleep(3000); + } + } + } + + /// + /// 日志写入文件 + /// + /// 文件名 + /// 日志 + private static void WriteLoggerToFile(string fname, List logs) + { + StringBuilder sb = new StringBuilder(); + logs.ForEach(s => sb.AppendLine(DateTime.Now.ToString("HH:mm:ss") + "\t" + s)); + if (!File.Exists(fname)) + { + using (StreamWriter sw = File.CreateText(fname)) + { + sw.Write(sb.ToString()); + } + } + else + { + using (StreamWriter sw = File.AppendText(fname)) + { + sw.Write(sb.ToString()); + } + } + } + #endregion + + #region 发布与打包锁 + /// + /// 查询锁定文件 + /// + /// + /// + /// + /// + public static bool LockDevFiles(Server server, string oprate) + { + bool b_in = false; + string lfname = GetTempFileName("lockfile"); + string rfname = $"/tmp/lockfile"; + if (SftpHelper.DownloadFile(server, rfname, lfname)) + { + if (File.Exists(lfname)) + { + SendLog(File.ReadAllText(lfname, Encoding.UTF8)); + b_in = true; + } + } + else + { + File.WriteAllText(lfname, $"当前服务器 {server.Ip} 繁忙。用户 [{Environment.MachineName}] 正在 {oprate},请等待 [{Environment.MachineName}] 操作完毕...", Encoding.UTF8); + SftpHelper.UploadFile(server, lfname, rfname); + } + return b_in; + } + + /// + /// 删除锁定文件 + /// + /// + public static void RemoveDevFiles(Server server) + { + SftpHelper.Delete(server, $"/tmp/lockfile"); + } + #endregion + + #region HTTP模板 + public static CookieContainer m_Cookies = new CookieContainer(); + public enum Compression + { + GZip, + Deflate, + None, + } + + /// + /// 获取HttpWebRequest模板 + /// + /// URL地址 + /// POST + /// Cookies + /// + public static HttpWebRequest GetHttpRequest(string url, string postdata, CookieContainer cookies, string header = null) + { + HttpWebRequest request = WebRequest.Create(new Uri(url)) as HttpWebRequest; + + request.CookieContainer = cookies; + request.ContentType = !string.IsNullOrEmpty(header) ? "application/json" : "application/x-www-form-urlencoded"; + request.ServicePoint.ConnectionLimit = 300; + ServicePointManager.Expect100Continue = false; + request.Referer = url; + request.Accept = "*/*"; + request.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)"; + request.AllowAutoRedirect = true; + if (!string.IsNullOrEmpty(header)) + request.Headers.Add("Authorization", header); + if (postdata != null && postdata != "") + { + request.Method = "POST"; + byte[] byte_post = Encoding.Default.GetBytes(postdata); + request.ContentLength = byte_post.Length; + using (Stream stream = request.GetRequestStream()) + { + stream.Write(byte_post, 0, byte_post.Length); + } + } + else + { + request.Method = "GET"; + } + return request; + } + + /// + /// 提取HttpWebResponse文本内容 + /// + /// HttpWebResponse响应包 + /// + public static string GetResponseContent(HttpWebResponse resp) + { + + if (resp.StatusCode != HttpStatusCode.OK) + throw new Exception("远程服务器返回状态码: " + resp.StatusCode); + + Encoding enc = Encoding.UTF8; + if (resp.CharacterSet != null && resp.CharacterSet != "") + enc = Encoding.GetEncoding(resp.CharacterSet); + + Compression comp = Compression.None; + if (resp.ContentEncoding != null && resp.ContentEncoding.Trim().ToUpper() == "GZIP") + comp = Compression.GZip; + else if (resp.ContentEncoding != null && resp.ContentEncoding.Trim().ToUpper() == "DEFLATE") + comp = Compression.Deflate; + + MemoryStream ms = new MemoryStream(); + using (StreamWriter sw = new StreamWriter(ms, enc)) + { + StreamReader sr; + switch (comp) + { + case Compression.GZip: + sr = new StreamReader(new System.IO.Compression.GZipStream(resp.GetResponseStream(), System.IO.Compression.CompressionMode.Decompress), enc); + break; + case Compression.Deflate: + sr = new StreamReader(new System.IO.Compression.DeflateStream(resp.GetResponseStream(), System.IO.Compression.CompressionMode.Decompress), enc); + break; + default: + sr = new StreamReader(resp.GetResponseStream(), enc); + break; + } + + while (!sr.EndOfStream) + { + char[] buf = new char[16000]; + int read = sr.ReadBlock(buf, 0, 16000); + StringBuilder sb = new StringBuilder(); + sb.Append(buf, 0, read); + sw.Write(buf, 0, read); + } + sr.Close(); + } + + byte[] mbuf = ms.GetBuffer(); + string sbuf = enc.GetString(mbuf); + return sbuf; + } + + /// + /// 获取HttpWebRequest返回值 + /// + /// URL地址 + /// PostData + /// + public static string GetHttpResult(string url, string postdata, string header = null) + { + try + { + HttpWebRequest request = GetHttpRequest(url, postdata, m_Cookies, header); + + HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + + m_Cookies.Add(response.Cookies); + + return GetResponseContent(response); + } + catch + { + //Utilities.sendLog("连接 " + url + " 失败" + ex.Message); + return ""; + } + } + + + /// + /// 获取HttpWebRequest返回值 + /// + /// URL地址 + /// PostData + /// + public static Stream GetHttpResponse(string url, string postdata) + { + try + { + HttpWebRequest request = GetHttpRequest(url, postdata, m_Cookies); + + HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + + return response.GetResponseStream(); + } + catch + { + //Utilities.sendLog("连接 " + url + " 失败" + ex.Message); + return null; + } + } + + /// + /// 去除HTML标记 + /// + /// 包括HTML的源码 + /// 已经去除后的文字 + public static string RemoveHTMLFlag(string input) + { + input = Regex.Replace(input, @"]*?>.*?", "", RegexOptions.IgnoreCase); + + Regex regex = new Regex("<.+?>", RegexOptions.IgnoreCase); + input = regex.Replace(input, ""); + input = Regex.Replace(input, @"<(.[^>]*)>", "", RegexOptions.IgnoreCase); + input = Regex.Replace(input, @"([\r\n])[\s]+", "", RegexOptions.IgnoreCase); + input = Regex.Replace(input, @"-->", "", RegexOptions.IgnoreCase); + input = Regex.Replace(input, @"