commit 437c251f58b818386e4629c1cf0e851a61294430 Author: yexingqiang Date: Mon Jun 8 17:19:25 2026 +0800 chore: 初始化平芝126KV总装线 WebApi diff --git a/Helpers/Gl.cs b/Helpers/Gl.cs new file mode 100644 index 0000000..d11fc84 --- /dev/null +++ b/Helpers/Gl.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Concurrent; +using WebApi.Models; + +namespace WebApi.Helpers +{ + /// + /// 全局变量类 + /// + public class Gl + { + /// + /// SQL Server连接状态 + /// + public static bool OnLine_Sql { get; set; } = false; + + /// + /// AGV连接状态 + /// + public static bool OnLine_AGV { get; set; } = false; + + /// + /// MQTT连接状态 + /// + public static bool OnLine_MQTT { get; set; } = false; + + public static ConcurrentDictionary TightenList { get; set; } = new ConcurrentDictionary(); + } +} \ No newline at end of file diff --git a/Helpers/Mqtt.cs b/Helpers/Mqtt.cs new file mode 100644 index 0000000..e281ad6 --- /dev/null +++ b/Helpers/Mqtt.cs @@ -0,0 +1,147 @@ +using Logger; +using MQTTnet; +using MQTTnet.Client; +using MQTTnet.Extensions.ManagedClient; +using MQTTnet.Server; +using System; +using System.Net.Sockets; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace WebApi.Helpers +{ + + public class Mqtt + { + public static IMqttClient mqttClient = null; + + public static event Action ConnectionStatusChanged; // 连接状态改变事件 + /// + /// Param1:ClientId + /// Param2:Topic + /// Param3:Message + /// + public static event Action MessageReceived; // 接收到消息事件 + + public static async Task RunMqttStart(string ip,int port,string username, string password) + { + try + { + string clientId = Guid.NewGuid().ToString(); + // Create a MQTT client factory + var factory = new MqttFactory(); + + // Create a MQTT client instance + mqttClient = factory.CreateMqttClient(); + + // 连接成功 + mqttClient.ConnectedAsync += (e => + { + ConnectionStatusChanged?.Invoke(true); + return Task.CompletedTask; + }); + // 连接断开 + mqttClient.DisconnectedAsync += (e => + { + ConnectionStatusChanged?.Invoke(false); + return Task.CompletedTask; + }); + // 收到消息 + mqttClient.ApplicationMessageReceivedAsync += (e => + { + string messagePayload = null; + if (e.ApplicationMessage.PayloadSegment.Count > 0) + { + byte[] payload = e.ApplicationMessage.PayloadSegment.Array; + int payloadOffset = e.ApplicationMessage.PayloadSegment.Offset; + int payloadLength = e.ApplicationMessage.PayloadSegment.Count; + messagePayload = Encoding.UTF8.GetString(payload, payloadOffset, payloadLength); + } + else + { + messagePayload = ""; + } + + MessageReceived?.Invoke(e.ClientId, e.ApplicationMessage.Topic, messagePayload); + return Task.CompletedTask; + }); + + // Create MQTT client options + var options = new MqttClientOptionsBuilder() + .WithTcpServer(ip, port) // MQTT broker address and port + .WithCredentials(username, password) // Set username and password + .WithClientId(clientId) + .WithCleanSession() + .Build(); + + // Connect to MQTT broker + var connectResult = await mqttClient.ConnectAsync(options); + } + catch (Exception ex) + { + Log.FunError(ex, MethodBase.GetCurrentMethod().Name); + } + } + + /// + /// 断开连接 + /// + /// + public static async Task RunMqttStop() + { + if (mqttClient != null) + { + await mqttClient.DisconnectAsync(); + mqttClient.Dispose(); + mqttClient = null; + } + } + + /// + /// 推送消息 + /// + /// + /// + /// + public static async Task RunMqttPublish(string topic, string message) + { + if (mqttClient != null) + { + var publishOptions = new MqttApplicationMessageBuilder() + .WithTopic(topic) + .WithPayload(message) + .WithRetainFlag(false) + .Build(); + + await mqttClient.PublishAsync(publishOptions); + } + } + + /// + /// 添加订阅 + /// + /// + /// + public static async Task RunMqttSubscribe(string topic) + { + if (mqttClient != null) + { + await mqttClient.SubscribeAsync(topic); + } + } + + /// + /// 取消订阅 + /// + /// + /// + public static async Task RunMqttUnSubscribe(string topic) + { + if (mqttClient != null) + { + await mqttClient.UnsubscribeAsync(topic); + } + } + } +} diff --git a/Helpers/SqlServer.cs b/Helpers/SqlServer.cs new file mode 100644 index 0000000..c966e6e --- /dev/null +++ b/Helpers/SqlServer.cs @@ -0,0 +1,223 @@ +using System; +using System.Data.SqlClient; +using System.Data; +using System.Reflection; +using Logger; +using System.Collections.Generic; + +namespace WebApi.Helpers +{ + public class SqlServer + { + public static bool ExecuteProcedure(string ProcedureName, SqlParameter[] sqlParameters, out DataTable dt, out string errorMessage) + { + bool result = false; + dt = new DataTable(); + errorMessage = ""; + using (SqlConnection sqlConnection = new SqlConnection(Tools.AppConfigManage.ReadConfig("ConnectionString"))) + { + try + { + sqlConnection.Open(); + // 开始事务 + SqlTransaction sqlTransaction = sqlConnection.BeginTransaction(); + try + { + using (SqlCommand sqlCommand = sqlConnection.CreateCommand()) + { + sqlCommand.Transaction = sqlTransaction; // 将事务附加到SqlCommand对象 + sqlCommand.CommandType = CommandType.StoredProcedure; + sqlCommand.CommandText = ProcedureName; + + if (sqlParameters != null) + { + for (int i = 0; i < sqlParameters.Length; i++) + { + sqlCommand.Parameters.Add(sqlParameters[i]); + } + } + + // 创建SqlDataAdapter并关联SqlCommand + using (SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand)) + { + // 填充DataTable + sqlDataAdapter.Fill(dt); + } + // 如果执行成功,提交事务 + sqlTransaction.Commit(); + result = true; + } + } + catch (Exception ex) + { + // 如果执行过程中出现异常,回滚事务 + try + { + sqlTransaction.Rollback(); + errorMessage = ProcedureName + "存储过程执行失败,事务已回滚。错误信息:" + ex.Message; + Log.Error(ProcedureName + "存储过程执行失败,事务已回滚。错误信息:" + ex.Message); + } + catch (Exception exRollback) + { + // 如果回滚操作也失败,记录回滚异常 + errorMessage = ProcedureName + "事务回滚失败。错误信息:" + exRollback.Message; + Log.Error(ProcedureName + "事务回滚失败。错误信息:" + exRollback.Message); + } + finally + { + if (sqlConnection.State == ConnectionState.Open) + { + sqlConnection.Close(); + } + } + } + } + catch (Exception ex) + { + errorMessage = ex.Message; + Log.FunError(ex, MethodBase.GetCurrentMethod().Name); + } + finally + { + if (sqlConnection.State == ConnectionState.Open) + { + sqlConnection.Close(); + } + } + } + return result; + } + public static bool ExecuteSql(string sql, out DataTable dt, out string errorMessage) + { + bool result = false; + dt = new DataTable(); + errorMessage = ""; + using (SqlConnection sqlConnection = new SqlConnection(Tools.AppConfigManage.ReadConfig("ConnectionString"))) + { + try + { + sqlConnection.Open(); + // 开始事务 + using (SqlTransaction sqlTransaction = sqlConnection.BeginTransaction()) + { + using (SqlCommand sqlCommand = new SqlCommand(sql, sqlConnection, sqlTransaction)) + { + sqlCommand.CommandType = CommandType.Text; // 设置为执行文本命令 + + // 创建SqlDataAdapter并关联SqlCommand + using (SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand)) + { + // 填充DataTable + sqlDataAdapter.Fill(dt); + } + + // 如果执行成功,提交事务 + sqlTransaction.Commit(); + result = true; + } + } + } + catch (Exception ex) + { + errorMessage = ex.Message; + Log.FunError(ex, MethodBase.GetCurrentMethod().Name); + } + finally + { + if (sqlConnection.State == ConnectionState.Open) + { + sqlConnection.Close(); + } + } + } + return result; + } + + public static bool ExecuteProcedure(string ProcedureName, Dictionary sqlParametersDictionary, out DataTable dt, out string errorMessage) + { + // 处理字典数据 转为 SqlParameter + List parameterList = new List (); + foreach (KeyValuePair param in sqlParametersDictionary) + { + parameterList.Add(new SqlParameter("@" + param.Key, param.Value)); + } + SqlParameter[] sqlParameters = parameterList.ToArray(); + + bool result = false; + dt = new DataTable(); + errorMessage = ""; + using (SqlConnection sqlConnection = new SqlConnection(Tools.AppConfigManage.ReadConfig("ConnectionString"))) + { + try + { + sqlConnection.Open(); + // 开始事务 + SqlTransaction sqlTransaction = sqlConnection.BeginTransaction(); + try + { + using (SqlCommand sqlCommand = sqlConnection.CreateCommand()) + { + sqlCommand.Transaction = sqlTransaction; // 将事务附加到SqlCommand对象 + sqlCommand.CommandType = CommandType.StoredProcedure; + sqlCommand.CommandText = ProcedureName; + + if (sqlParameters != null) + { + for (int i = 0; i < sqlParameters.Length; i++) + { + sqlCommand.Parameters.Add(sqlParameters[i]); + } + } + + // 创建SqlDataAdapter并关联SqlCommand + using (SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand)) + { + // 填充DataTable + sqlDataAdapter.Fill(dt); + } + // 如果执行成功,提交事务 + sqlTransaction.Commit(); + result = true; + } + } + catch (Exception ex) + { + // 如果执行过程中出现异常,回滚事务 + try + { + sqlTransaction.Rollback(); + errorMessage = ProcedureName + "存储过程执行失败,事务已回滚。错误信息:" + ex.Message; + Log.Error(ProcedureName + "存储过程执行失败,事务已回滚。错误信息:" + ex.Message); + } + catch (Exception exRollback) + { + // 如果回滚操作也失败,记录回滚异常 + errorMessage = ProcedureName + "事务回滚失败。错误信息:" + exRollback.Message; + Log.Error(ProcedureName + "事务回滚失败。错误信息:" + exRollback.Message); + } + finally + { + if (sqlConnection.State == ConnectionState.Open) + { + sqlConnection.Close(); + } + } + } + } + catch (Exception ex) + { + errorMessage = ex.Message; + Log.FunError(ex, MethodBase.GetCurrentMethod().Name); + } + finally + { + if (sqlConnection.State == ConnectionState.Open) + { + sqlConnection.Close(); + } + } + } + return result; + } + } +} diff --git a/MainView.Designer.cs b/MainView.Designer.cs new file mode 100644 index 0000000..2f4f20b --- /dev/null +++ b/MainView.Designer.cs @@ -0,0 +1,301 @@ +namespace WebApi +{ + partial class MainView + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows 窗体设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要修改 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainView)); + this.MessageTable = new AntdUI.Table(); + this.divider1 = new AntdUI.Divider(); + this.divider2 = new AntdUI.Divider(); + this.collapse1 = new AntdUI.Collapse(); + this.panel8 = new System.Windows.Forms.Panel(); + this.label9 = new System.Windows.Forms.Label(); + this.pb_OnLine_Sql = new System.Windows.Forms.PictureBox(); + this.panel1 = new System.Windows.Forms.Panel(); + this.label1 = new System.Windows.Forms.Label(); + this.pb_OnLine_MQTT = new System.Windows.Forms.PictureBox(); + this.panel2 = new System.Windows.Forms.Panel(); + this.label2 = new System.Windows.Forms.Label(); + this.pb_OnLine_AGV = new System.Windows.Forms.PictureBox(); + this.timer_OnLine_Show = new System.Windows.Forms.Timer(this.components); + this.TightenTable = new AntdUI.Table(); + this.ClearLog = new AntdUI.Button(); + this.logCountLab = new AntdUI.Label(); + this.divider3 = new AntdUI.Divider(); + this.panel8.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pb_OnLine_Sql)).BeginInit(); + this.panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pb_OnLine_MQTT)).BeginInit(); + this.panel2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pb_OnLine_AGV)).BeginInit(); + this.SuspendLayout(); + // + // MessageTable + // + this.MessageTable.Location = new System.Drawing.Point(670, 62); + this.MessageTable.Name = "MessageTable"; + this.MessageTable.Size = new System.Drawing.Size(884, 796); + this.MessageTable.TabIndex = 0; + this.MessageTable.Text = "table1"; + // + // divider1 + // + this.divider1.Location = new System.Drawing.Point(781, 170); + this.divider1.Name = "divider1"; + this.divider1.Size = new System.Drawing.Size(8, 8); + this.divider1.TabIndex = 1; + this.divider1.Text = "divider1"; + // + // divider2 + // + this.divider2.Location = new System.Drawing.Point(670, 12); + this.divider2.Name = "divider2"; + this.divider2.Size = new System.Drawing.Size(609, 36); + this.divider2.TabIndex = 2; + this.divider2.Text = "日志"; + // + // collapse1 + // + this.collapse1.Location = new System.Drawing.Point(105, 197); + this.collapse1.Name = "collapse1"; + this.collapse1.Size = new System.Drawing.Size(37, 11); + this.collapse1.TabIndex = 3; + this.collapse1.Text = "collapse1"; + // + // panel8 + // + this.panel8.BackColor = System.Drawing.Color.Gainsboro; + this.panel8.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.panel8.Controls.Add(this.label9); + this.panel8.Controls.Add(this.pb_OnLine_Sql); + this.panel8.Location = new System.Drawing.Point(37, 41); + this.panel8.Margin = new System.Windows.Forms.Padding(4); + this.panel8.Name = "panel8"; + this.panel8.Size = new System.Drawing.Size(150, 149); + this.panel8.TabIndex = 1801; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold); + this.label9.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.label9.Location = new System.Drawing.Point(30, 20); + this.label9.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(86, 31); + this.label9.TabIndex = 1; + this.label9.Text = "服务器"; + // + // pb_OnLine_Sql + // + this.pb_OnLine_Sql.ErrorImage = global::WebApi.Properties.Resources.断开状态; + this.pb_OnLine_Sql.Image = global::WebApi.Properties.Resources.断开连接; + this.pb_OnLine_Sql.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.pb_OnLine_Sql.Location = new System.Drawing.Point(36, 62); + this.pb_OnLine_Sql.Margin = new System.Windows.Forms.Padding(4); + this.pb_OnLine_Sql.Name = "pb_OnLine_Sql"; + this.pb_OnLine_Sql.Size = new System.Drawing.Size(76, 78); + this.pb_OnLine_Sql.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.pb_OnLine_Sql.TabIndex = 16; + this.pb_OnLine_Sql.TabStop = false; + // + // panel1 + // + this.panel1.BackColor = System.Drawing.Color.Gainsboro; + this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.panel1.Controls.Add(this.label1); + this.panel1.Controls.Add(this.pb_OnLine_MQTT); + this.panel1.Location = new System.Drawing.Point(250, 41); + this.panel1.Margin = new System.Windows.Forms.Padding(4); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(150, 149); + this.panel1.TabIndex = 1801; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold); + this.label1.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.label1.Location = new System.Drawing.Point(30, 20); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(89, 31); + this.label1.TabIndex = 1; + this.label1.Text = "MQTT"; + // + // pb_OnLine_MQTT + // + this.pb_OnLine_MQTT.ErrorImage = global::WebApi.Properties.Resources.断开状态; + this.pb_OnLine_MQTT.Image = global::WebApi.Properties.Resources.断开连接; + this.pb_OnLine_MQTT.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.pb_OnLine_MQTT.Location = new System.Drawing.Point(36, 62); + this.pb_OnLine_MQTT.Margin = new System.Windows.Forms.Padding(4); + this.pb_OnLine_MQTT.Name = "pb_OnLine_MQTT"; + this.pb_OnLine_MQTT.Size = new System.Drawing.Size(76, 78); + this.pb_OnLine_MQTT.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.pb_OnLine_MQTT.TabIndex = 16; + this.pb_OnLine_MQTT.TabStop = false; + // + // panel2 + // + this.panel2.BackColor = System.Drawing.Color.Gainsboro; + this.panel2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.panel2.Controls.Add(this.label2); + this.panel2.Controls.Add(this.pb_OnLine_AGV); + this.panel2.Location = new System.Drawing.Point(468, 41); + this.panel2.Margin = new System.Windows.Forms.Padding(4); + this.panel2.Name = "panel2"; + this.panel2.Size = new System.Drawing.Size(150, 149); + this.panel2.TabIndex = 1801; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold); + this.label2.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.label2.Location = new System.Drawing.Point(40, 20); + this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(67, 31); + this.label2.TabIndex = 1; + this.label2.Text = "AGV"; + // + // pb_OnLine_AGV + // + this.pb_OnLine_AGV.ErrorImage = global::WebApi.Properties.Resources.断开状态; + this.pb_OnLine_AGV.Image = global::WebApi.Properties.Resources.断开连接; + this.pb_OnLine_AGV.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.pb_OnLine_AGV.Location = new System.Drawing.Point(36, 62); + this.pb_OnLine_AGV.Margin = new System.Windows.Forms.Padding(4); + this.pb_OnLine_AGV.Name = "pb_OnLine_AGV"; + this.pb_OnLine_AGV.Size = new System.Drawing.Size(76, 78); + this.pb_OnLine_AGV.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.pb_OnLine_AGV.TabIndex = 16; + this.pb_OnLine_AGV.TabStop = false; + // + // timer_OnLine_Show + // + this.timer_OnLine_Show.Enabled = true; + this.timer_OnLine_Show.Interval = 3000; + this.timer_OnLine_Show.Tick += new System.EventHandler(this.timer1_Tick); + // + // TightenTable + // + this.TightenTable.Location = new System.Drawing.Point(12, 436); + this.TightenTable.Name = "TightenTable"; + this.TightenTable.Size = new System.Drawing.Size(606, 437); + this.TightenTable.TabIndex = 1802; + this.TightenTable.Text = "IPTable"; + // + // ClearLog + // + this.ClearLog.Location = new System.Drawing.Point(1442, 5); + this.ClearLog.Name = "ClearLog"; + this.ClearLog.Size = new System.Drawing.Size(136, 57); + this.ClearLog.TabIndex = 1803; + this.ClearLog.Text = "清空日志"; + this.ClearLog.Type = AntdUI.TTypeMini.Warn; + this.ClearLog.Click += new System.EventHandler(this.ClearLog_Click); + // + // logCountLab + // + this.logCountLab.BackColor = System.Drawing.SystemColors.AppWorkspace; + this.logCountLab.Font = new System.Drawing.Font("方正舒体", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.logCountLab.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(255))))); + this.logCountLab.LocalizationSuffix = "条"; + this.logCountLab.Location = new System.Drawing.Point(1289, 12); + this.logCountLab.Name = "logCountLab"; + this.logCountLab.Size = new System.Drawing.Size(147, 44); + this.logCountLab.TabIndex = 1804; + this.logCountLab.Text = "9999条"; + this.logCountLab.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // divider3 + // + this.divider3.Location = new System.Drawing.Point(9, 404); + this.divider3.Name = "divider3"; + this.divider3.Size = new System.Drawing.Size(609, 36); + this.divider3.TabIndex = 2; + this.divider3.Text = "拧紧扳手"; + // + // MainView + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1582, 885); + this.Controls.Add(this.logCountLab); + this.Controls.Add(this.ClearLog); + this.Controls.Add(this.TightenTable); + this.Controls.Add(this.panel2); + this.Controls.Add(this.panel1); + this.Controls.Add(this.panel8); + this.Controls.Add(this.collapse1); + this.Controls.Add(this.divider3); + this.Controls.Add(this.divider2); + this.Controls.Add(this.divider1); + this.Controls.Add(this.MessageTable); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "MainView"; + this.Text = "MESController"; + this.panel8.ResumeLayout(false); + this.panel8.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pb_OnLine_Sql)).EndInit(); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pb_OnLine_MQTT)).EndInit(); + this.panel2.ResumeLayout(false); + this.panel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pb_OnLine_AGV)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private AntdUI.Table MessageTable; + private AntdUI.Divider divider1; + private AntdUI.Divider divider2; + private AntdUI.Collapse collapse1; + private System.Windows.Forms.Panel panel8; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.PictureBox pb_OnLine_Sql; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.PictureBox pb_OnLine_MQTT; + private System.Windows.Forms.Panel panel2; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.PictureBox pb_OnLine_AGV; + private System.Windows.Forms.Timer timer_OnLine_Show; + private AntdUI.Table TightenTable; + private AntdUI.Button ClearLog; + private AntdUI.Label logCountLab; + private AntdUI.Divider divider3; + } +} + diff --git a/MainView.cs b/MainView.cs new file mode 100644 index 0000000..63b69c4 --- /dev/null +++ b/MainView.cs @@ -0,0 +1,292 @@ +using AntdUI; +using Logger; +using MQTTnet.Server; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Net.NetworkInformation; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using WebApi.Helpers; +using static WebApi.MainView; + +namespace WebApi +{ + public partial class MainView : Form + { + + InitServer initServer = null; + static BindingList msgTableList = new BindingList(); + static BindingList tightenTableList = new BindingList(); + + + public MainView() + { + InitializeComponent(); + InitUI(); + AddMessage("程序启动--------------------------"); + initServer = new WebApi.InitServer(Convert.ToInt32(Tools.AppConfigManage.ReadConfig("WebApiPort"))); + MqttServer.StartMqttServer(); + ServerController.ShowMsg += AddMessage; + MqttServer.ShowMsg += AddMessage; + Show_OnLineStateAsync(); + + Tighten.TightenServer tighten = new Tighten.TightenServer(); + Task.Run(() => tighten.InitTightenList()); + Tighten.TightenServer.ShowMsg += AddMessage; + Log.ShowMsg += AddMessage; + + // 添加关闭程序的二次确认 + this.FormClosing += MainView_FormClosing; + } + + private void InitUI() + { + MessageTable.Columns = new AntdUI.ColumnCollection { + new AntdUI.Column("dateTime","消息时间"){ Fixed=false,Width="140"}, + new AntdUI.Column("msg","消息内容"){ Fixed=false,Width="440",LineBreak=true}, + }; + MessageTable.Binding(msgTableList); + + TightenTable.Columns = new AntdUI.ColumnCollection { + new AntdUI.Column("name","名称"){ Fixed=true}, + new AntdUI.Column("ip","IP"){ Fixed=true}, + new AntdUI.Column("isConnect","状态",AntdUI.ColumnAlign.Center), + }; + TightenTable.Binding(tightenTableList); + } + + private void AddMessage(string message) + { + // 如果大于1000条,删除最后一条 + if (msgTableList.Count > 1000) + { + msgTableList.RemoveAt(msgTableList.Count - 1); + } + msgTableList.Insert(0, new msgTableClass(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), message)); + logCountLab.Text = msgTableList.Count.ToString() + "条"; + } + + public class msgTableClass : AntdUI.NotifyProperty + { + public msgTableClass(string dateTime, string msg) + { + _dateTime = dateTime; + _msg = msg; + } + + string _dateTime; + public string dateTime + { get => _dateTime; set { if (_dateTime == value) return; _dateTime = value; OnPropertyChanged("dateTime"); } } + + string _msg; + public string msg + { get => _msg; set { if (_msg == value) return; _msg = value; OnPropertyChanged("msg"); } } + } + + public class tightenTableClass : AntdUI.NotifyProperty + { + public tightenTableClass(string name,string ip, bool isConnect) + { + _name = name; + _ip = ip; + if (isConnect) _isConnect = new AntdUI.CellBadge(AntdUI.TState.Success, "在线"); + else _isConnect = new AntdUI.CellBadge(AntdUI.TState.Error, "离线"); + } + + string _name; + public string name + { get => _name; set { if (_name == value) return; _name = value; OnPropertyChanged("name"); } } + + string _ip; + public string ip + { get => _ip; set { if (_ip == value) return; _ip = value; OnPropertyChanged("ip"); } } + + AntdUI.CellBadge _isConnect; + public AntdUI.CellBadge isConnect + { + get => _isConnect; set { _isConnect = value; OnPropertyChanged("isConnect"); } + } + } + + private async void timer1_Tick(object sender, EventArgs e) + { + timer_OnLine_Show.Enabled = false; + await Show_OnLineStateAsync(); + RefreshTightenStatus(); + timer_OnLine_Show.Enabled = true; + } + + private async Task Show_OnLineStateAsync() + { + await OnLineStatus_CheckAsync(); + + // UI更新需要在主线程执行 + this.Invoke((MethodInvoker)delegate + { + OnLineState_C(pb_OnLine_Sql, Gl.OnLine_Sql); + OnLineState_C(pb_OnLine_AGV, Gl.OnLine_AGV); + OnLineState_C(pb_OnLine_MQTT, Gl.OnLine_MQTT); + }); + } + + /// + /// 显示通讯状态 + /// + /// + /// + private void OnLineState_C(PictureBox pb, bool onLine) + { + pb.Image = onLine ? global::WebApi.Properties.Resources.连接 + : global::WebApi.Properties.Resources.断开连接; + } + + public static async Task OnLineStatus_CheckAsync() + { + // 并行检查所有连接状态 + var tasks = new List + { + CheckSqlConnectionAsync(), + CheckAgvConnectionAsync(), + CheckMqttConnectionAsync() + }; + + await Task.WhenAll(tasks); + } + + private static async Task CheckSqlConnectionAsync() + { + try + { + await Task.Run(() => + { + SqlServer.ExecuteSql("select getdate()", out DataTable dt, out string err); + Gl.OnLine_Sql = string.IsNullOrEmpty(err); + }); + } + catch (Exception) + { + Gl.OnLine_Sql = false; + } + } + + private static async Task CheckAgvConnectionAsync() + { + try + { + await Task.Run(() => + { + Gl.OnLine_AGV = Ping(Tools.AppConfigManage.ReadConfig("AGVIP")); + }); + } + catch (Exception) + { + Gl.OnLine_AGV = false; + } + } + + private static async Task CheckMqttConnectionAsync() + { + try + { + await Task.Run(() => + { + Gl.OnLine_MQTT = MqttServer.IsConnected(); + }); + } + catch (Exception) + { + Gl.OnLine_MQTT = false; + } + } + + private static bool Ping(string ip) + { + try + { + using (var ping = new Ping()) + { + return ping.Send(ip, 1000).Status == IPStatus.Success; + } + } + catch + { + return false; + } + } + + private void RefreshTightenStatus() + { + tightenTableList.Clear(); + var sortedList = WebApi.Helpers.Gl.TightenList.Values.OrderBy(tool => tool.IP); + foreach (var tool in sortedList) + { + tightenTableList.Add(new tightenTableClass(tool.Name, tool.IP, tool.TcpClient != null && tool.TcpClient.Connected)); + } + } + + private void ClearLog_Click(object sender, EventArgs e) + { + msgTableList.Clear(); + logCountLab.Text = msgTableList.Count.ToString() + "条"; + } + + /// + /// 窗体关闭时的确认处理 + /// + /// + /// + private void MainView_FormClosing(object sender, FormClosingEventArgs e) + { + // 显示确认对话框 + DialogResult result = MessageBox.Show( + "确定要关闭程序吗?\n\n关闭程序将停止所有服务(WebAPI、MQTT等)。", + "关闭确认", + MessageBoxButtons.YesNo, + MessageBoxIcon.Question, + MessageBoxDefaultButton.Button2 + ); + + // 如果用户点击"否",则取消关闭 + if (result == DialogResult.No) + { + e.Cancel = true; + AddMessage("用户取消关闭程序"); + return; + } + + // 用户确认关闭,记录日志并执行清理工作 + AddMessage("程序正在关闭..."); + + try + { + // 停止定时器 + if (timer_OnLine_Show != null) + { + timer_OnLine_Show.Stop(); + timer_OnLine_Show.Dispose(); + } + + // 停止MQTT服务器(异步方法,使用Wait()等待完成) + Task.Run(async () => await MqttServer.StopMqttServer()).Wait(); + + // 停止WebAPI服务器 + if (initServer != null) + { + initServer.Close(); + } + + AddMessage("程序关闭完成"); + } + catch (Exception ex) + { + AddMessage($"关闭程序时发生错误: {ex.Message}"); + } + } + } +} diff --git a/MainView.resx b/MainView.resx new file mode 100644 index 0000000..8541d33 --- /dev/null +++ b/MainView.resx @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + 70 + + + + + AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAABMLAAATCwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMgChADIAoQIyAKEgMgChczIA + occyAKHqMgChmTIAoTwyAKEJMgChAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMgChADIAoQQyAKEvMgChdzIA + odYyAKH7MgCh/zIAof8yAKH/MgCh6jIAoacyAKFJMgChEjIAoQAyAKEAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyAKEAMgChADIAoQoyAKE+MgChkTIA + oeoyAKH+MgCh+TIAoe0yAKH+MgCh/zIAofwyAKH3MgCh/jIAofgyAKHBMgChZDIAoR4yAKEBMgChAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyAKEAMgChATIAoRUyAKFcMgChujIA + ofEyAKH/MgCh9DIAobcyAKFPMgChfjIAof8yAKH/MgCh5TIAoVUyAKGLMgCh4jIAofwyAKH9MgCh2TIA + oYcyAKEoMgChBTIAoQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyAKEAMgChAjIAoSYyAKF2MgCh0DIA + ofcyAKH+MgCh8zIAof8yAKGjMgChDTIAoQAyAKFpMgCh/zIAof8yAKHhMgChHjIAoQIyAKEiMgChbjIA + ocoyAKH3MgCh/jIAoeUyAKGfMgChQTIAoQsyAKEAAAAAAAAAAAAAAAAAMgChCDIAoUEyAKGXMgCh4jIA + of4yAKH/MgChzzIAoW0yAKFoMgCh+zIAoZcyAKEAMgChADIAoWkyAKH/MgCh/zIAoeEyAKEeMgChADIA + oQAyAKEBMgChETIAoVAyAKGiMgCh8DIAof8yAKH0MgChuTIAoW0yAKEVMgChADIAoQAyAKG2MgCh7TIA + of8yAKHvMgCh7jIAofgyAKFLMgChADIAoTcyAKH1MgChlzIAoQAyAKEAMgChaTIAof8yAKH/MgCh4TIA + oR4yAKEAAAAAAAAAAAAAAAAAMgChADIAoQcyAKE4MgChijIAod8yAKH9MgCh+zIAoc4yAKFdMgChADIA + of8yAKHlMgChlDIAoToyAKGgMgCh7jIAoSwyAKEAMgChFzIAodgyAKGZMgChADIAoQAyAKFpMgCh/zIA + of8yAKHxMgChfDIAoSkyAKEBMgChAAAAAAAAAAAAAAAAADIAoQAyAKECMgChITIAoW8yAKG/MgCh/zIA + oZYyAKEAMgCh/zIAoZoyAKEBMgChADIAoZkyAKHSMgChEjIAoQAyAKEGMgChujIAoZoyAKEAMgChADIA + oWkyAKH/MgCh/zIAof0yAKH+MgCh4TIAoZIyAKFEMgChDjIAoQAyAKEAAAAAAAAAAAAAAAAAMgChADIA + oUIyAKH7MgChlzIAoQAyAKH/MgChlzIAoQAyAKEAMgChmjIAobMyAKEEMgChADIAoQAyAKGcMgChmzIA + oQAyAKEAMgChaTIAof8yAKH/MgCh4zIAoZYyAKHRMgCh+zIAofQyAKHDMgChZDIAoSIyAKEBMgChAAAA + AAAyAKEAMgChPzIAofsyAKGXMgChADIAof8yAKGXMgChADIAoQAyAKGaMgChiDIAoQAAAAAAMgChADIA + oYgyAKGaMgChADIAoQAyAKFpMgCh/zIAof8yAKHhMgChIDIAoRIyAKFeMgChqzIAoe0yAKH+MgCh3jIA + oYYyAKEqMgChADIAoQAyAKE/MgCh+zIAoZcyAKEAMgCh/zIAoZcyAKEAMgChADIAoZgyAKFtMgChAAAA + AAAyAKEAMgChXDIAoZQyAKEAMgChADIAoWkyAKH/MgCh/zIAoeEyAKEeMgChADIAoQAyAKEGMgChMDIA + oX8yAKHTMgCh+jIAoWkyAKEAMgChADIAoT8yAKH7MgChlzIAoQAyAKH/MgChlzIAoQAyAKEAMgChlTIA + oWMyAKEAAAAAADIAoQAyAKE2MgChhTIAoQAyAKEAMgChaTIAof8yAKH/MgCh4TIAoR4yAKEAAAAAAAAA + AAAyAKEAMgChATIAoRUyAKFYMgChQDIAoQAyAKEAMgChPzIAofsyAKGXMgChADIAof8yAKGXMgChADIA + oQAyAKGLMgChQTIAoQAyAKEFMgChADIAoSMyAKF4MgChADIAoQAyAKFpMgCh/zIAof8yAKHhMgChHjIA + oQAAAAAAAAAAAAAAAAAAAAAAMgChADIAoQAyAKEBMgChADIAoQAyAKE/MgCh+zIAoZcyAKEAMgCh/zIA + oZcyAKEAMgChADIAoXcyAKEkMgChBzIAoUIyAKEBMgChFjIAoWUyAKEBMgChADIAoWkyAKH/MgCh/zIA + oeEyAKEeMgChADIAoQAyAKE5MgChSTIAoQ8yAKEBMgChAAAAAAAAAAAAMgChADIAoT8yAKH7MgChlzIA + oQAyAKH/MgChlzIAoQAyAKECMgChWzIAoQ8yAKEVMgChhTIAoQoyAKEHMgChMzIAoQEyAKEAMgChaTIA + of8yAKH/MgCh4TIAoR4yAKEAMgChADIAoWkyAKH1MgChyzIAoX8yAKE4MgChBTIAoQAyAKEAMgChPzIA + ofsyAKGXMgChADIAof8yAKGXMgChADIAoQMyAKFZMgChCzIAoS4yAKHDMgChGjIAoQAAAAAAAAAAADIA + oQAyAKFpMgCh/zIAof8yAKHhMgChHjIAoQAyAKEAMgChLDIAoaEyAKHkMgCh/DIAoe8yAKGrMgChUzIA + oREyAKFBMgCh+zIAoZcyAKEAMgCh/zIAoZcyAKEAMgChBzIAoVAyAKEEMgChQTIAodoyAKEjMgChAAAA + AAAAAAAAMgChADIAoWkyAKH/MgCh/zIAoeEyAKEeMgChAAAAAAAyAKEAMgChBjIAoSAyAKFyMgChwjIA + ofMyAKH4MgCh0zIAobMyAKH9MgChljIAoQAyAKH/MgChlzIAoQAyAKEBMgChBDIAoQAyAKFKMgCh7jIA + oT0yAKEAAAAAADIAoQAyAKEAMgChbDIAof8yAKH/MgCh4TIAoR8yAKEAAAAAAAAAAAAAAAAAMgChADIA + oQEyAKELMgChRzIAoZYyAKHeMgCh/TIAof8yAKGWMgChADIAof8yAKGXMgChAAAAAAAAAAAAMgChADIA + oW0yAKH/MgChZDIAoQAyAKEEMgChHDIAoWAyAKHPMgCh/zIAof8yAKH3MgChkTIAoS8yAKELMgChADIA + oQAAAAAAAAAAAAAAAAAyAKEAMgChATIAoSAyAKF2MgCh/zIAoZYyAKEAMgCh/zIAoZcyAKEAAAAAADIA + oQAyAKEAMgChljIAof8yAKGeMgChOTIAoZEyAKHcMgCh+TIAof8yAKH/MgCh/zIAof8yAKH+MgCh6jIA + obgyAKFXMgChITIAoQEyAKEAAAAAAAAAAAAAAAAAMgChADIAoT8yAKH7MgChlzIAoQAyAKH/MgChlzIA + oQAAAAAAMgChADIAoQwyAKG9MgCh/zIAofMyAKHyMgCh/jIAof8yAKH/MgCh/zIAofoyAKH3MgCh/jIA + of8yAKH/MgCh/zIAofsyAKHbMgChmzIAoUwyAKENMgChATIAoQAyAKEAMgChPzIAofsyAKGXMgChADIA + of8yAKGXMgChATIAoRkyAKFbMgChsTIAofAyAKH/MgCh/zIAof8yAKH/MgCh/DIAoeYyAKGxMgChVTIA + oUIyAKGFMgCh1TIAofUyAKH/MgCh/zIAof8yAKH/MgCh9DIAocUyAKGDMgChMDIAoQYyAKE/MgCh+zIA + oZcyAKEAMgCh/zIAocEyAKGOMgCh2TIAofcyAKH/MgCh/zIAof8yAKH/MgCh7jIAobMyAKFwMgChJjIA + oQoyAKEAMgChADIAoQEyAKEXMgChTTIAoZsyAKHYMgCh/TIAof8yAKH/MgCh/zIAof4yAKHqMgChszIA + oZgyAKH+MgChljIAoQAyAKH/MgCh/zIAof8yAKH/MgCh/zIAof8yAKH0MgChyTIAoYEyAKE/MgChBzIA + oQAAAAAAMgChADIAoSIyAKF2MgChQjIAoRIyAKEAMgChATIAoR4yAKFjMgChrjIAoecyAKH9MgCh/zIA + of8yAKH/MgCh/zIAof8yAKGWMgChADIAof8yAKH/MgCh/zIAofkyAKHWMgChmjIAoUIyAKERMgChATIA + oQAyAKEGMgChFTIAoQMyAKEAMgChKDIAoZUyAKHHMgChxjIAoXcyAKE3MgChBzIAoQAyAKEGMgChKTIA + oXYyAKHDMgCh7jIAof4yAKH/MgCh/zIAoZYyAKEAMgChrjIAoeYyAKH+MgCh0zIAoVcyAKELMgChADIA + oQAyAKEAMgChADIAoVUyAKHAMgChkjIAoVYyAKEUMgChATIAoRYyAKFhMgChqzIAodUyAKGmMgChZTIA + oR8yAKEDMgChBDIAoS0yAKGiMgCh9DIAofUyAKHGMgChWTIAoQAyAKEGMgChKjIAoWsyAKHBMgCh3DIA + ocEyAKFwMgChJTIAoQYyAKEAMgChDDIAoTgyAKF/MgChyjIAocMyAKGUMgChMzIAoQsyAKEEMgChJjIA + oWUyAKG/MgCh0TIAoaYyAKGoMgCh1TIAodYyAKGNMgChQTIAoRAyAKEAMgChAAAAAAAyAKEAMgChADIA + oQ8yAKE8MgChkDIAoc8yAKHfMgChpDIAoVIyAKEcMgChADIAoQEyAKETMgChRzIAoZ8yAKHGMgChvzIA + oWQyAKEtMgChMzIAoY8yAKHvMgCh5zIAoa8yAKFcMgChHDIAoQMyAKEAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAADIAoQAyAKECMgChFTIAoVcyAKGaMgCh3DIAodEyAKGaMgChSDIAoQsyAKEAMgChATIA + oSUyAKGGMgCh6TIAofEyAKHhMgChtzIAoXAyAKErMgChBTIAoQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMgChADIAoQIyAKElMgChXTIAobgyAKHbMgChxTIA + oYUyAKFbMgChqzIAodEyAKHLMgChhDIAoTsyAKELMgChAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyAKEAMgChCzIA + oTcyAKGTMgCh0zIAofAyAKG2MgChWjIAoRcyAKEBMgChAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/+Af//+AB//8AAD/8AAAP8AIAA8AGDABARg+AQEYD4ERGAPxMZgAcTOY + ADEzmDAxM5g8MTKIPzEgCDDxIAgwMSB4MAEgeDgBJHg+ATxAD8E8AAHxOAAAMQAAAAEAAwABABwgAQBE + BAEBwAABAEAAA+AAAA/4AAB//wAD///gD/8= + + + \ No newline at end of file diff --git a/Models/Req/AGV_To_MES_AgvPass_Req.cs b/Models/Req/AGV_To_MES_AgvPass_Req.cs new file mode 100644 index 0000000..ab95d96 --- /dev/null +++ b/Models/Req/AGV_To_MES_AgvPass_Req.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WebApi.Models +{ + /// + /// AGV发送 到位 离开信号 + /// + public class AGV_To_MES_AgvPass_Req + { + /// + /// 第三方任务编号,系统唯一不可重复 + /// + public string taskId + { + get; + set; + } + + /// + /// 工位号 + /// + public string station + { + get; + set; + } + + /// + /// 工件编号 + /// + public string EngineNo + { + get; + set; + } + + /// + /// 机型号 + /// + public string SortNo + { + get; + set; + } + + /// + /// 推送类型:0到位,1离开 当前只推送到位,保留离开推送 + /// + public int type + { + get; + set; + } + } +} diff --git a/Models/Req/MES_To_AGV_From_WEB_Req.cs b/Models/Req/MES_To_AGV_From_WEB_Req.cs new file mode 100644 index 0000000..c230574 --- /dev/null +++ b/Models/Req/MES_To_AGV_From_WEB_Req.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WebApi.Models +{ + /// + /// 从前端发来的请求发往AGV + /// + public class MES_To_AGV_From_WEB_Req + { + /// + /// 请求URL 只携带最后一个单词 + /// + public string url + { + get; + set; + } + + /// + /// 携带的请求参数 + /// + public object data + { + get; + set; + } + } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..7666d7a --- /dev/null +++ b/Program.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Threading; +using System.IO; +using System.Text; + +namespace WebApi +{ + internal static class Program + { + /// + /// 应用程序的主入口点。 + /// + [STAThread] + static void Main() + { + // 设置全局异常处理 + SetupGlobalExceptionHandling(); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainView()); + } + + /// + /// 设置全局异常处理 + /// + private static void SetupGlobalExceptionHandling() + { + // 设置异常处理模式,让程序继续运行而不是崩溃 + Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); + + // 处理UI线程异常 + Application.ThreadException += Application_ThreadException; + + // 处理非UI线程异常 + AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; + } + + /// + /// 处理UI线程异常 + /// + /// + /// + private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) + { + try + { + string errorMessage = GetExceptionDetails(e.Exception); + + // 记录异常日志 + LogException(errorMessage, "UI线程异常"); + + // 显示友好的错误提示 + MessageBox.Show( + $"程序遇到错误,但已自动处理,程序将继续运行。\n\n错误信息:{e.Exception.Message}\n\n详细信息已记录到日志文件中。", + "程序错误", + MessageBoxButtons.OK, + MessageBoxIcon.Warning + ); + } + catch (Exception ex) + { + // 如果异常处理本身出错,至少尝试显示基本信息 + MessageBox.Show($"程序遇到严重错误:{ex.Message}", "严重错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + /// + /// 处理非UI线程异常 + /// + /// + /// + private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + try + { + Exception exception = e.ExceptionObject as Exception; + if (exception != null) + { + string errorMessage = GetExceptionDetails(exception); + + // 记录异常日志 + LogException(errorMessage, "非UI线程异常"); + + // 如果是终止性异常,显示更严重的提示 + if (e.IsTerminating) + { + MessageBox.Show( + $"程序遇到严重错误,可能需要重启。\n\n错误信息:{exception.Message}\n\n详细信息已记录到日志文件中。", + "严重错误", + MessageBoxButtons.OK, + MessageBoxIcon.Error + ); + } + } + } + catch (Exception ex) + { + // 最后的保险措施 + MessageBox.Show($"程序遇到无法处理的错误:{ex.Message}", "致命错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + /// + /// 获取异常详细信息 + /// + /// + /// + private static string GetExceptionDetails(Exception exception) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine($"异常时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss}"); + sb.AppendLine($"异常类型:{exception.GetType().Name}"); + sb.AppendLine($"异常消息:{exception.Message}"); + sb.AppendLine($"异常堆栈:{exception.StackTrace}"); + + if (exception.InnerException != null) + { + sb.AppendLine("内部异常:"); + sb.AppendLine(GetExceptionDetails(exception.InnerException)); + } + + return sb.ToString(); + } + + /// + /// 记录异常日志 + /// + /// + /// + private static void LogException(string errorMessage, string exceptionType) + { + try + { + string logDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs"); + if (!Directory.Exists(logDir)) + { + Directory.CreateDirectory(logDir); + } + + string logFile = Path.Combine(logDir, $"Exception_{DateTime.Now:yyyy-MM-dd}.log"); + + StringBuilder logContent = new StringBuilder(); + logContent.AppendLine($"==================== {exceptionType} ===================="); + logContent.AppendLine(errorMessage); + logContent.AppendLine(new string('=', 50)); + logContent.AppendLine(); + + File.AppendAllText(logFile, logContent.ToString(), Encoding.UTF8); + } + catch + { + // 如果日志记录失败,也不要抛出异常 + } + } + } +} diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8140e7c --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("WebApi")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WebApi")] +[assembly: AssemblyCopyright("Copyright © 2025")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("64dfb865-859c-478b-96c6-ab52dcb1de92")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs new file mode 100644 index 0000000..267d3c9 --- /dev/null +++ b/Properties/Resources.Designer.cs @@ -0,0 +1,873 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace WebApi.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WebApi.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性,对 + /// 使用此强类型资源类的所有资源查找执行重写。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap _002_列表 { + get { + object obj = ResourceManager.GetObject("002_列表", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap _0780fca3def52d8a02649c7aa2f8093a { + get { + object obj = ResourceManager.GetObject("0780fca3def52d8a02649c7aa2f8093a", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap action_Cancel_16xLG { + get { + object obj = ResourceManager.GetObject("action_Cancel_16xLG", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap BOSS_数据管理 { + get { + object obj = ResourceManager.GetObject("BOSS-数据管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap HMI { + get { + object obj = ResourceManager.GetObject("HMI", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap JD { + get { + object obj = ResourceManager.GetObject("JD", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap MBE风格多色图标_密码 { + get { + object obj = ResourceManager.GetObject("MBE风格多色图标-密码", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap panlClose { + get { + object obj = ResourceManager.GetObject("panlClose", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap ssbj { + get { + object obj = ResourceManager.GetObject("ssbj", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap staticjd { + get { + object obj = ResourceManager.GetObject("staticjd", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 上传 { + get { + object obj = ResourceManager.GetObject("上传", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 上载 { + get { + object obj = ResourceManager.GetObject("上载", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 下载 { + get { + object obj = ResourceManager.GetObject("下载", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 业务 { + get { + object obj = ResourceManager.GetObject("业务", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 任务监控和查询 { + get { + object obj = ResourceManager.GetObject("任务监控和查询", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 保存 { + get { + object obj = ResourceManager.GetObject("保存", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 信息_记录 { + get { + object obj = ResourceManager.GetObject("信息_记录", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 关闭 { + get { + object obj = ResourceManager.GetObject("关闭", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 关闭系统 { + get { + object obj = ResourceManager.GetObject("关闭系统", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 写入托盘 { + get { + object obj = ResourceManager.GetObject("写入托盘", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 分布图 { + get { + object obj = ResourceManager.GetObject("分布图", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 列表 { + get { + object obj = ResourceManager.GetObject("列表", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 列表2 { + get { + object obj = ResourceManager.GetObject("列表2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 删除 { + get { + object obj = ResourceManager.GetObject("删除", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 刷新 { + get { + object obj = ResourceManager.GetObject("刷新", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 动态数据查询 { + get { + object obj = ResourceManager.GetObject("动态数据查询", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 合作 { + get { + object obj = ResourceManager.GetObject("合作", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 图表_柱 { + get { + object obj = ResourceManager.GetObject("图表_柱", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 图表_线_通用_统计 { + get { + object obj = ResourceManager.GetObject("图表_线_通用_统计", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 图表_饼 { + get { + object obj = ResourceManager.GetObject("图表_饼", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 增加 { + get { + object obj = ResourceManager.GetObject("增加", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 备份_复制 { + get { + object obj = ResourceManager.GetObject("备份_复制", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 审核_盖章 { + get { + object obj = ResourceManager.GetObject("审核_盖章", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 密码 { + get { + object obj = ResourceManager.GetObject("密码", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 导入 { + get { + object obj = ResourceManager.GetObject("导入", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 导出 { + get { + object obj = ResourceManager.GetObject("导出", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 工作台 { + get { + object obj = ResourceManager.GetObject("工作台", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 工具 { + get { + object obj = ResourceManager.GetObject("工具", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 布局图 { + get { + object obj = ResourceManager.GetObject("布局图", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 帮助 { + get { + object obj = ResourceManager.GetObject("帮助", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 异常_危险 { + get { + object obj = ResourceManager.GetObject("异常_危险", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 手动打印 { + get { + object obj = ResourceManager.GetObject("手动打印", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 打印机 { + get { + object obj = ResourceManager.GetObject("打印机", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 按键分割线 { + get { + object obj = ResourceManager.GetObject("按键分割线", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 按键分割线浅 { + get { + object obj = ResourceManager.GetObject("按键分割线浅", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 搜索 { + get { + object obj = ResourceManager.GetObject("搜索", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 操作管理 { + get { + object obj = ResourceManager.GetObject("操作管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 文档 { + get { + object obj = ResourceManager.GetObject("文档", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 断开 { + get { + object obj = ResourceManager.GetObject("断开", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 断开状态 { + get { + object obj = ResourceManager.GetObject("断开状态", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 断开连接 { + get { + object obj = ResourceManager.GetObject("断开连接", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 新增_添加 { + get { + object obj = ResourceManager.GetObject("新增_添加", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 日志 { + get { + object obj = ResourceManager.GetObject("日志", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 更多 { + get { + object obj = ResourceManager.GetObject("更多", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 权限角色管理 { + get { + object obj = ResourceManager.GetObject("权限角色管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 正确_成功 { + get { + object obj = ResourceManager.GetObject("正确_成功", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 添加 { + get { + object obj = ResourceManager.GetObject("添加", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 用户_账号_我的 { + get { + object obj = ResourceManager.GetObject("用户_账号_我的", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 用户_账号_我的_未登录 { + get { + object obj = ResourceManager.GetObject("用户_账号_我的_未登录", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 登出2 { + get { + object obj = ResourceManager.GetObject("登出2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 登录 { + get { + object obj = ResourceManager.GetObject("登录", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 筛选 { + get { + object obj = ResourceManager.GetObject("筛选", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 系统管理 { + get { + object obj = ResourceManager.GetObject("系统管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 系统管理和监控服务 { + get { + object obj = ResourceManager.GetObject("系统管理和监控服务", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 组群_角色 { + get { + object obj = ResourceManager.GetObject("组群_角色", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 编辑_修改 { + get { + object obj = ResourceManager.GetObject("编辑_修改", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 解锁 { + get { + object obj = ResourceManager.GetObject("解锁", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 记录2 { + get { + object obj = ResourceManager.GetObject("记录2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 质控管理 { + get { + object obj = ResourceManager.GetObject("质控管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 辅助_协助 { + get { + object obj = ResourceManager.GetObject("辅助_协助", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 返回2 { + get { + object obj = ResourceManager.GetObject("返回2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 进度_沙漏 { + get { + object obj = ResourceManager.GetObject("进度_沙漏", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 连接 { + get { + object obj = ResourceManager.GetObject("连接", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 连接状态 { + get { + object obj = ResourceManager.GetObject("连接状态", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 退出 { + get { + object obj = ResourceManager.GetObject("退出", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 配置 { + get { + object obj = ResourceManager.GetObject("配置", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 配置2 { + get { + object obj = ResourceManager.GetObject("配置2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 重新加载数据 { + get { + object obj = ResourceManager.GetObject("重新加载数据", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 锁定 { + get { + object obj = ResourceManager.GetObject("锁定", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 错误_失败 { + get { + object obj = ResourceManager.GetObject("错误_失败", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 零件管理 { + get { + object obj = ResourceManager.GetObject("零件管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/Properties/Resources.resx b/Properties/Resources.resx new file mode 100644 index 0000000..00fe6d8 --- /dev/null +++ b/Properties/Resources.resx @@ -0,0 +1,364 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + ..\icon\002_列表.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\0780fca3def52d8a02649c7aa2f8093a.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\action_Cancel_16xLG.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\BOSS-数据管理.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\HMI.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\JD.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\MBE风格多色图标-密码.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\panlClose.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\ssbj.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\staticjd.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\按键分割线.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\按键分割线浅.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\帮助.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\保存.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\备份_复制.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\编辑_修改.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\布局图.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\操作管理.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\错误_失败.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\打印机.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\导出.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\导入.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\登出2.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\登录.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\动态数据查询.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\断开.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\断开连接.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\断开状态.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\返回2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\分布图.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\辅助_协助.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\更多.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\工具.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\工作台.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\关闭.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\关闭系统.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\合作.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\记录2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\解锁.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\进度_沙漏.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\连接.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\连接状态.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\列表.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\列表2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\零件管理.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\密码.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\配置.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\配置2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\权限角色管理.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\任务监控和查询.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\日志.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\筛选.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\删除.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\上传.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\上载.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\审核_盖章.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\手动打印.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\刷新.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\搜索.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\锁定.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\添加.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\图表_饼.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\图表_线_通用_统计.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\图表_柱.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\退出.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\文档.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\系统管理.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\系统管理和监控服务.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\下载.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\写入托盘.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\新增_添加.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\信息_记录.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\业务.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\异常_危险.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\用户_账号_我的.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\用户_账号_我的_未登录.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\增加.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\正确_成功.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\质控管理.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\重新加载数据.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icon\组群_角色.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs new file mode 100644 index 0000000..f47e27b --- /dev/null +++ b/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace WebApi.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Properties/Settings.settings b/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Server/MqttServer.cs b/Server/MqttServer.cs new file mode 100644 index 0000000..94c9f45 --- /dev/null +++ b/Server/MqttServer.cs @@ -0,0 +1,215 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WebApi.Helpers; +using Logger; +using System.Reflection; +using System.Threading; + +namespace WebApi +{ + public class MqttServer + { + private static string mqttTopic; + private static string mqttIp; + private static int mqttPort; + private static bool isConnected = false; + private static bool isReconnecting = false; + private static CancellationTokenSource reconnectCancellation; + public static event Action ShowMsg; // 记录日志事件 + + public static async Task StartMqttServer() + { + try + { + reconnectCancellation = new CancellationTokenSource(); + + // 从配置文件读取MQTT配置 + string mqttConfig = Tools.AppConfigManage.ReadConfig("mqttIp"); + if (!string.IsNullOrEmpty(mqttConfig)) + { + var parts = mqttConfig.Split(','); + if (parts.Length == 2) + { + mqttIp = parts[0]; + mqttPort = Convert.ToInt32(parts[1]); + } + } + + mqttTopic = Tools.AppConfigManage.ReadConfig("mqttTopic"); + + // 注册MQTT事件处理 + Mqtt.ConnectionStatusChanged += OnMqttConnectionStatusChanged; + //Mqtt.MessageReceived += OnMqttMessageReceived; + + await ConnectToMqttServer(); + } + catch (Exception ex) + { + Log.FunError(ex, MethodBase.GetCurrentMethod().Name); + // 如果首次连接失败,也启动重连 + await StartReconnection(); + } + } + + private static async Task ConnectToMqttServer() + { + try + { + // 连接MQTT服务器 + await Mqtt.RunMqttStart(mqttIp, mqttPort, "", ""); + + // 订阅主题 + if (!string.IsNullOrEmpty(mqttTopic)) + { + await Mqtt.RunMqttSubscribe(mqttTopic); + } + } + catch (Exception ex) + { + Log.FunError(ex, MethodBase.GetCurrentMethod().Name); + throw; + } + } + + private static async Task StartReconnection() + { + if (isReconnecting) return; + + try + { + isReconnecting = true; + int retryCount = 0; + int maxRetryInterval = 10; // 最大重试间隔(秒) + + while (!isConnected && !reconnectCancellation.Token.IsCancellationRequested) + { + try + { + retryCount++; + // 计算重试间隔(指数退避),但不超过最大间隔 + double delaySeconds = Math.Min(Math.Pow(2, retryCount - 1), maxRetryInterval); + ShowMsg?.Invoke($"MQTT准备重连,{delaySeconds}秒后重试..."); + + await Task.Delay(TimeSpan.FromSeconds(delaySeconds), reconnectCancellation.Token); + await ConnectToMqttServer(); + } + catch (Exception ex) + { + Log.FunError(ex, "MQTT重连失败"); + } + } + } + finally + { + isReconnecting = false; + } + } + + private static void OnMqttConnectionStatusChanged(bool connected) + { + isConnected = connected; + if (connected) + { + ShowMsg?.Invoke($"MQTT已连接到服务器 {mqttIp}:{mqttPort}"); + } + else + { + ShowMsg?.Invoke($"MQTT已断开连接"); + // 启动重连 + Task.Run(StartReconnection); + } + } + + private static void OnMqttMessageReceived(string clientId, string topic, string message) + { + try + { + ShowMsg?.Invoke($"收到MQTT消息: Topic={topic}, Message={message}"); + // 这里可以添加消息处理逻辑 + if (topic == mqttTopic) + { + // 处理特定主题的消息 + } + } + catch (Exception ex) + { + Log.FunError(ex, MethodBase.GetCurrentMethod().Name); + } + } + + public static async Task StopMqttServer() + { + try + { + // 停止重连 + if (reconnectCancellation != null) + { + reconnectCancellation.Cancel(); + reconnectCancellation.Dispose(); + reconnectCancellation = null; + } + + // 取消订阅 + if (!string.IsNullOrEmpty(mqttTopic)) + { + await Mqtt.RunMqttUnSubscribe(mqttTopic); + } + + // 断开连接 + await Mqtt.RunMqttStop(); + + // 取消事件注册 + Mqtt.ConnectionStatusChanged -= OnMqttConnectionStatusChanged; + //Mqtt.MessageReceived -= OnMqttMessageReceived; + } + catch (Exception ex) + { + Log.FunError(ex, MethodBase.GetCurrentMethod().Name); + } + } + + public static bool IsConnected() + { + return isConnected; + } + + /// + /// 发送MQTT消息 + /// + /// 要发送的消息内容到工位 + /// + public static async Task SendMqttMessageToOp(string opName, string type, string value) + { + try + { + if (!MqttServer.IsConnected()) + { + ShowMsg?.Invoke("MQTT未连接,无法发送消息"); + return false; + } + + string mqttTopic = Tools.AppConfigManage.ReadConfig("mqttTopic"); + if (string.IsNullOrEmpty(mqttTopic)) + { + ShowMsg?.Invoke("MQTT主题未配置"); + return false; + } + string sendMsg = $"MES|{type}|{opName}|{value}"; + // MES/InstantMessaging/PZ126/OP010 + // MES|AGVStatus|OP010|1 + await Mqtt.RunMqttPublish(mqttTopic + opName, sendMsg); + ShowMsg?.Invoke($"MQTTSend: Topic={mqttTopic}, Message={sendMsg}"); + return true; + } + catch (Exception ex) + { + Log.FunError(ex, MethodBase.GetCurrentMethod().Name); + return false; + } + } + } +} + diff --git a/Tighten/Helpers/TightenHelpers.cs b/Tighten/Helpers/TightenHelpers.cs new file mode 100644 index 0000000..2ca6e96 --- /dev/null +++ b/Tighten/Helpers/TightenHelpers.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; + +namespace WebApi.Tighten +{ + public class TightenHelpers + { + public static bool Send(TcpClient tcpClient, string command,out string errMsg) + { + bool send = false; + errMsg = ""; + try + { + var sendstr = command.Replace(" ", ""); + byte[] commandbyte = Encoding.Default.GetBytes(sendstr); + tcpClient.Client.Send(commandbyte, SocketFlags.None); + send = true; + } + catch (Exception err) + { + errMsg = err.Message; + send = false; + } + return send; + } + + public static string Read(TcpClient tcpClient, out string errMsg) + { + errMsg = ""; + string command = ""; + if (tcpClient != null && tcpClient.Connected) + { + try + { + byte[] byteCommand = new byte[1024]; + int icommand = tcpClient.Client.Receive(byteCommand); + command = System.Text.Encoding.ASCII.GetString(byteCommand, 0, icommand); + } + catch(Exception ex) { + errMsg = ex.Message; + } + } + return command; + } + + public static void ParseTorqueData(string input, out double minTorque, out double maxTorque, out double targetTorque, out double actualTorque) + { + // 初始化默认值 + minTorque = maxTorque = targetTorque = actualTorque = 0; + + // 检查输入长度是否足够(至少需要146字符) + if (input == null || input.Length < 146) + { + throw new ArgumentException("输入字符串长度不足"); + } + + // 解析扭矩最小值(字节117-122,索引116-121) + string torqueMinStr = input.Substring(116, 6); + if (int.TryParse(torqueMinStr, out int torqueMinInt)) + minTorque = torqueMinInt / 100.0; + + // 解析扭矩最大值(字节125-130,索引124-129) + string torqueMaxStr = input.Substring(124, 6); + if (int.TryParse(torqueMaxStr, out int torqueMaxInt)) + maxTorque = torqueMaxInt / 100.0; + + // 解析扭矩目标值(字节133-138,索引132-137) + string torqueTargetStr = input.Substring(132, 6); + if (int.TryParse(torqueTargetStr, out int torqueTargetInt)) + targetTorque = torqueTargetInt / 100.0; + + // 解析实际扭矩值(字节141-146,索引140-145) + string torqueActualStr = input.Substring(140, 6); + if (int.TryParse(torqueActualStr, out int torqueActualInt)) + actualTorque = torqueActualInt / 100.0; + } + } +} diff --git a/Tighten/Models/TightenTool.cs b/Tighten/Models/TightenTool.cs new file mode 100644 index 0000000..7731025 --- /dev/null +++ b/Tighten/Models/TightenTool.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; + +namespace WebApi.Models +{ + public class TightenTool + { + public readonly object TcpClientLock = new object(); + /// + /// 工位号 + /// + public string OpName + { + get; + set; + } + /// + /// 拧紧枪名称 + /// + public string Name + { + get; + set; + } + /// + /// IP + /// + public string IP + { + get; + set; + } + /// + /// 端口号 + /// + public string Port + { + get; + set; + } + + /// + /// TPC客户端 + /// + public TcpClient TcpClient + { + get; + set; + } + + /// + /// 安全判断TcpClient是否已连接 + /// + public bool IsConnected + { + get { return TcpClient != null && TcpClient.Connected; } + } + } +} diff --git a/Tighten/TightenServer.cs b/Tighten/TightenServer.cs new file mode 100644 index 0000000..e4f797e --- /dev/null +++ b/Tighten/TightenServer.cs @@ -0,0 +1,256 @@ +using Logger; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Net.Http; +using System.Net.Sockets; +using System.Reflection; +using System.Runtime.Remoting.Contexts; +using System.Security.Cryptography; +using System.Security.Policy; +using System.Text; +using System.Threading.Tasks; +using WebApi.Helpers; +using WebApi.Models; + +namespace WebApi.Tighten +{ + public class TightenServer + { + Dictionary SendCode = new Dictionary + { + { "connect", "0020 0001 0050 0001 0000" }, // 建立通讯 + { "heart", "00209999001000010000" }, // 心跳 + { "curve", "00200900000000000000" }, // 曲线 + { "result", "00200060001000010000" }, // 订阅结果 + { "tightenOk", "00200062001000000000" } // 确认收到结果 + }; + public static event Action ShowMsg; // 记录日志事件 + + private bool _heartbeatRunning = false; + + public void InitTightenList() + { + RedTightenList(); + //Connect(); + StartHeartbeatLoop(); + StartReadData(); + } + + public void Connect() + { + try + { + foreach (KeyValuePair kvp in Gl.TightenList) + { + if (!kvp.Value.IsConnected) + { + kvp.Value.TcpClient.Connect(kvp.Value.IP, Convert.ToInt32(kvp.Value.Port)); + if (kvp.Value.IsConnected) + { + string ErrMsg; + // 创建工具连接 + if (!TightenHelpers.Send(kvp.Value.TcpClient, SendCode["connect"], out ErrMsg)) + { + Log.Error(kvp.Value.IP + ":" + ErrMsg); + return; + } + // 心跳 + if (!TightenHelpers.Send(kvp.Value.TcpClient, SendCode["heart"], out ErrMsg)) + { + Log.Error(kvp.Value.IP + ":" + ErrMsg); + return; + } + // 订阅结果 + if (!TightenHelpers.Send(kvp.Value.TcpClient, SendCode["result"], out ErrMsg)) + { + Log.Error(kvp.Value.IP + ":" + ErrMsg); + return; + } + } + } + + } + } + catch (Exception ex) { + Log.FunError(ex, MethodBase.GetCurrentMethod().Name); + } + } + + private void RedTightenList() + { + SqlServer.ExecuteSql("SELECT * FROM PTCHV_基础表_拧紧枪", out DataTable dt, out string err); + if (dt.Rows.Count > 0) + { + foreach (DataRow dr in dt.Rows) { + var tool = new TightenTool(); + tool.OpName = dr["OpName"].ToString(); + tool.Name = dr["Name"].ToString(); + tool.IP = dr["IP"].ToString(); + tool.Port = dr["Port"].ToString(); + tool.TcpClient = new System.Net.Sockets.TcpClient(); + Gl.TightenList.TryAdd(tool.IP, tool); + } + } + } + + private bool SaveTightenData(string opName,string toolName,string max,string min,string OkValue,string value) + { + bool isOk = false; + var param = new Dictionary{ + { "工位号", opName }, + { "拧紧枪名称", toolName }, + { "上限值", max }, + { "下限值", min }, + { "标准值", OkValue }, + { "值", value } + }; + SqlServer.ExecuteProcedure("PTCHV_质量数据_增加", param, out DataTable dt, out string err); + if (dt.Rows.Count > 0) + { + if(dt.Rows[0]["result"].ToString() == "1") + { + isOk = true; + } + } + return isOk; + } + + // 开启心跳轮询 同时监听数据 + public void StartHeartbeatLoop() + { + foreach (var kvp in Gl.TightenList) + { + var tool = kvp.Value; + Task.Run(async () => + { + while (true) + { + try + { + if (tool.TcpClient == null) + tool.TcpClient = new TcpClient(); + + if (!tool.IsConnected) + { + try + { + tool.TcpClient.Close(); + } + catch { } + tool.TcpClient = new TcpClient(); + // 连接加超时 + var connectTask = tool.TcpClient.ConnectAsync(tool.IP, Convert.ToInt32(tool.Port)); + if (await Task.WhenAny(connectTask, Task.Delay(3000)) == connectTask) + { + // 连接成功 + string errMsg; + TightenHelpers.Send(tool.TcpClient, SendCode["connect"], out errMsg); + TightenHelpers.Send(tool.TcpClient, SendCode["heart"], out errMsg); + TightenHelpers.Send(tool.TcpClient, SendCode["result"], out errMsg); + if(errMsg == "") + { + Log.Info($"拧紧枪【{tool.Name}】 连接成功!"); + } + } + else + { + //Log.Error($"{tool.IP} 连接超时"); + } + } + else + { + string errMsg; + TightenHelpers.Send(tool.TcpClient, SendCode["heart"], out errMsg); + } + } + catch (Exception ex) + { + Log.FunError(ex, "HeartbeatLoop"); + } + await Task.Delay(10000); + } + }); + } + } + + public void StartReadData() + { + foreach (var kvp in Gl.TightenList) + { + Task.Run(async () => + { + while (true) + { + var tool = kvp.Value; + string ErrMsg = ""; + try + { + var client = tool.TcpClient; + bool isConnected = false; + try + { + isConnected = client?.Client?.Connected ?? false; + } + catch (ObjectDisposedException) + { + isConnected = false; + } + catch (Exception ex) + { + Log.Error($"检查连接状态时发生意外错误 for {tool.IP}: {ex.Message}"); + isConnected = false; + } + + if (isConnected) + { + string command = ""; + try + { + if(client != null) + command = TightenHelpers.Read(client, out ErrMsg); + else + continue; + + if(ErrMsg != "") + { + Log.Error("【ReadErr】"+kvp.Value.IP + ":" + ErrMsg); + } + + if (command.Length == 232) + { + TightenHelpers.ParseTorqueData(command, out double min, out double max, out double target, out double actual); + ShowMsg?.Invoke($"【{tool.OpName}{tool.Name} 拧紧数据】最小扭矩: {min}, 最大扭矩: {max}, 目标扭矩: {target}, 实际扭矩: {actual}"); + SaveTightenData(tool.OpName, tool.Name, max.ToString(), min.ToString(), target.ToString(), actual.ToString()); + await MqttServer.SendMqttMessageToOp(tool.OpName, "TightenOk", "1"); + // 发送确认前再次检查连接状态 + bool canSend = false; + try + { + canSend = client?.Client?.Connected ?? false; + } catch { /* ignore */ } + + if (canSend) + { + TightenHelpers.Send(client, SendCode["tightenOk"], out ErrMsg); + } + } + } + catch (Exception readSendEx) // 捕获读取或发送过程中的异常 + { + Log.Error($"读取或发送数据时出错 for {tool.IP}: {readSendEx.Message}"); + try { client?.Close(); } catch { } + tool.TcpClient = null; // 标记以便下次循环重建 + } + } + } catch (Exception outerEx) { + Log.FunError(outerEx, MethodBase.GetCurrentMethod().Name); + } + await Task.Delay(50); + } + }); + } + } + } +} diff --git a/TightenSetting.xlsx b/TightenSetting.xlsx new file mode 100644 index 0000000..bf7d584 Binary files /dev/null and b/TightenSetting.xlsx differ diff --git a/Tools/AppConfigManage.cs b/Tools/AppConfigManage.cs new file mode 100644 index 0000000..dfc5c17 --- /dev/null +++ b/Tools/AppConfigManage.cs @@ -0,0 +1,113 @@ +using Logger; +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Configuration; +using System.Xml; + +namespace Tools +{ + public class AppConfigManage + { + public static Dictionary ReadConfigList() + { + + Dictionary appSettingsDictionary = new Dictionary(); + var appSettings = ConfigurationManager.AppSettings; + foreach (var key in appSettings.AllKeys) + { + appSettingsDictionary.Add(key, appSettings[key]); + } + return appSettingsDictionary; + } + + public static string ReadConfig(string key) + { + return ConfigurationManager.AppSettings[key]; + } + + public static void DeleteConfig(string key) + { + // 获取配置文件路径 + string configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).FilePath; + Configuration config = ConfigurationManager.OpenExeConfiguration(configFile); + + // 加载xml文件 + XmlDocument xDoc = new XmlDocument(); + xDoc.Load(configFile); + + // 获取appSettings节点 + XmlNode xNode = xDoc.SelectSingleNode("//appSettings"); + if (xNode != null) + { + // 查找并删除指定的节点 + XmlNode toRemove = xNode.SelectSingleNode($"add[@key='{key}']"); + if (toRemove != null) + { + xNode.RemoveChild(toRemove); + config.AppSettings.Settings.Remove(key); + } + } + // 保存xml文档 + xDoc.Save(configFile); + + // 保存配置文件 + config.Save(ConfigurationSaveMode.Modified); + // 刷新配置节,以便ConfigurationManager使用最新的配置 + ConfigurationManager.RefreshSection("appSettings"); + } + + public static void SaveConfig(string key, string value) + { + try + { + // 获取配置文件路径 + string configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).FilePath; + Configuration config = ConfigurationManager.OpenExeConfiguration(configFile); + KeyValueConfigurationElement setting = config.AppSettings.Settings[key]; + + XmlDocument xDoc = new XmlDocument(); + xDoc.Load(configFile);//加载xml文件 + + XmlNode xNode; + XmlElement xElem1; + XmlElement xElem2; + + xNode = xDoc.SelectSingleNode("//appSettings");//获取指定的xml子节点 + xElem1 = (XmlElement)xNode.SelectSingleNode($"//add[@key='{key}']");//获取子节点中指定的子节点 + //如果能获取到节点,就修改节点的value值 + if (xElem1 != null) + { + xElem1.SetAttribute("value", value);//给节点中的value属性赋值(修改操作) + } + //如果不能获取到节点,就创建节点 + else + { + xElem2 = xDoc.CreateElement("add"); + xElem2.SetAttribute("key", key); + xElem2.SetAttribute("value", value); + xNode.AppendChild(xElem2); + } + + if (setting != null) + { + setting.Value = value; + } + else + { + config.AppSettings.Settings.Add(key, value); + } + + xDoc.Save(configFile);//保存xml文档 + + config.Save(ConfigurationSaveMode.Modified); + ConfigurationManager.RefreshSection("appSettings"); + + } + catch (Exception ex) + { + Log.FunError(ex, MethodBase.GetCurrentMethod().Name); + } + } + } +} diff --git a/Tools/Logger.cs b/Tools/Logger.cs new file mode 100644 index 0000000..5d02ee7 --- /dev/null +++ b/Tools/Logger.cs @@ -0,0 +1,96 @@ +using Serilog; +using Serilog.Events; +using Serilog.Formatting; +using System; +using System.IO; +using System.Security.Policy; + +namespace Logger +{ + public static class Log + { + private static readonly ILogger logger; + public static event Action ShowMsg; // 记录日志事件 + + static Log() + { + string logpath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $@"Logs\Log_{DateTime.Now:yyyy-MM-dd}.html"); + logger = new LoggerConfiguration() + .MinimumLevel.Debug() + .WriteTo.File(new HtmlFormatter(), logpath, + rollingInterval: RollingInterval.Day, + rollOnFileSizeLimit: true, + retainedFileCountLimit: 7, + fileSizeLimitBytes: 1000 * 1024) + .CreateLogger(); + } + + public static void Error(string message) + { + ShowMsg?.Invoke(message); + logger.Error(message); + } + + public static void FunError(Exception ex, string funName) + { + ShowMsg?.Invoke(funName + " — FunErr — " + ex.Message); + logger.Error(funName + " — FunErr — " + ex.Message); + } + + public static void Info(string message) + { + ShowMsg?.Invoke(message); + logger.Information(message); + } + + public static void Debug(string message) + { + ShowMsg?.Invoke(message); + logger.Debug(message); + } + + public static void Warning(string message) + { + ShowMsg?.Invoke(message); + logger.Warning(message); + } + + public static void Fatal(string message) + { + ShowMsg?.Invoke(message); + logger.Fatal(message); + } + } + + public class HtmlFormatter : ITextFormatter + { + public void Format(LogEvent logEvent, TextWriter output) + { + string levelColor = GetLevelColor(logEvent.Level); + string message = logEvent.RenderMessage(); + + output.WriteLine($"
"); + output.WriteLine($"

[{logEvent.Timestamp:yyyy-MM-dd HH:mm:ss}] [{logEvent.Level}] {message}

"); + output.WriteLine("
"); + } + + private string GetLevelColor(LogEventLevel level) + { + switch (level) + { + case LogEventLevel.Debug: + return "gray"; + case LogEventLevel.Information: + return "black"; + case LogEventLevel.Warning: + return "orange"; + case LogEventLevel.Error: + return "red"; + case LogEventLevel.Fatal: + return "purple"; + default: + return "black"; + } + } + } +} diff --git a/WebApi.csproj b/WebApi.csproj new file mode 100644 index 0000000..69be9e4 --- /dev/null +++ b/WebApi.csproj @@ -0,0 +1,493 @@ + + + + + Debug + AnyCPU + {64DFB865-859C-478B-96C6-AB52DCB1DE92} + WinExe + WebApi + WebApi + v4.8 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + packages\AntdUI.1.9.4\lib\net48\AntdUI.dll + + + packages\Microsoft.AspNetCore.Http.Abstractions.2.3.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Abstractions.dll + + + packages\Microsoft.AspNetCore.Http.Extensions.2.3.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Extensions.dll + + + packages\Microsoft.AspNetCore.Http.Features.2.3.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Features.dll + + + packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + + + packages\Microsoft.Extensions.Configuration.Abstractions.8.0.0\lib\net462\Microsoft.Extensions.Configuration.Abstractions.dll + + + packages\Microsoft.Extensions.DependencyInjection.Abstractions.8.0.2\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + packages\Microsoft.Extensions.FileProviders.Abstractions.8.0.0\lib\net462\Microsoft.Extensions.FileProviders.Abstractions.dll + + + packages\Microsoft.Extensions.Logging.Abstractions.8.0.2\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll + + + packages\Microsoft.Extensions.Options.8.0.2\lib\net462\Microsoft.Extensions.Options.dll + + + packages\Microsoft.Extensions.Primitives.8.0.0\lib\net462\Microsoft.Extensions.Primitives.dll + + + packages\Microsoft.Net.Http.Headers.2.3.0\lib\netstandard2.0\Microsoft.Net.Http.Headers.dll + + + packages\Microsoft.Owin.4.2.2\lib\net45\Microsoft.Owin.dll + + + packages\MQTTnet.4.3.7.1207\lib\net48\MQTTnet.dll + + + packages\MQTTnet.Extensions.ManagedClient.4.3.7.1207\lib\net48\MQTTnet.Extensions.ManagedClient.dll + + + packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + + + packages\Newtonsoft.Json.Bson.1.0.2\lib\net45\Newtonsoft.Json.Bson.dll + + + packages\Owin.1.0\lib\net40\Owin.dll + + + packages\Serilog.4.2.0\lib\net471\Serilog.dll + + + packages\Serilog.Sinks.File.6.0.0\lib\net471\Serilog.Sinks.File.dll + + + + packages\System.Buffers.4.6.0\lib\net462\System.Buffers.dll + + + + + + + + packages\System.Diagnostics.DiagnosticSource.8.0.1\lib\net462\System.Diagnostics.DiagnosticSource.dll + + + packages\System.IO.4.3.0\lib\net462\System.IO.dll + True + True + + + packages\System.Memory.4.5.5\lib\net461\System.Memory.dll + + + packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll + True + True + + + packages\Microsoft.AspNet.WebApi.Client.6.0.0\lib\net45\System.Net.Http.Formatting.dll + + + + packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll + True + True + + + packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net463\System.Security.Cryptography.Algorithms.dll + True + True + + + packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + True + True + + + packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + True + True + + + packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + True + True + + + packages\System.Text.Encodings.Web.8.0.0\lib\net462\System.Text.Encodings.Web.dll + + + packages\System.Threading.Channels.8.0.0\lib\net462\System.Threading.Channels.dll + + + packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + + packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll + + + packages\Microsoft.AspNet.Cors.5.3.0\lib\net45\System.Web.Cors.dll + + + packages\Microsoft.AspNet.WebApi.Core.5.3.0\lib\net45\System.Web.Http.dll + + + packages\Microsoft.AspNet.WebApi.Cors.5.3.0\lib\net45\System.Web.Http.Cors.dll + + + packages\Microsoft.AspNet.WebApi.Owin.5.3.0\lib\net45\System.Web.Http.Owin.dll + + + packages\Microsoft.AspNet.WebApi.SelfHost.5.3.0\lib\net45\System.Web.Http.SelfHost.dll + + + + + + + + + + + + + + + + Form + + + MainView.cs + + + + + + + + + + + + + + + + + + + + MainView.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WebApi.sln b/WebApi.sln new file mode 100644 index 0000000..2744fc0 --- /dev/null +++ b/WebApi.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.35122.118 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApi", "WebApi.csproj", "{64DFB865-859C-478B-96C6-AB52DCB1DE92}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {64DFB865-859C-478B-96C6-AB52DCB1DE92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {64DFB865-859C-478B-96C6-AB52DCB1DE92}.Debug|Any CPU.Build.0 = Debug|Any CPU + {64DFB865-859C-478B-96C6-AB52DCB1DE92}.Release|Any CPU.ActiveCfg = Release|Any CPU + {64DFB865-859C-478B-96C6-AB52DCB1DE92}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B28EDDAB-DA2D-415B-B254-D0051DAE4C96} + EndGlobalSection +EndGlobal diff --git a/WebApi/BusinessController.cs b/WebApi/BusinessController.cs new file mode 100644 index 0000000..24ad80c --- /dev/null +++ b/WebApi/BusinessController.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WebApi +{ + public class BusinessController + { + } +} diff --git a/WebApi/Helpers/Gl.cs b/WebApi/Helpers/Gl.cs new file mode 100644 index 0000000..0846a25 --- /dev/null +++ b/WebApi/Helpers/Gl.cs @@ -0,0 +1,25 @@ +using System; + +namespace WebApi.Helpers +{ + /// + /// 全局变量类 + /// + public class Gl + { + /// + /// SQL Server连接状态 + /// + public static bool OnLine_Sql { get; set; } = false; + + /// + /// AGV连接状态 + /// + public static bool OnLine_AGV { get; set; } = false; + + /// + /// MQTT连接状态 + /// + public static bool OnLine_MQTT { get; set; } = false; + } +} \ No newline at end of file diff --git a/WebApi/Helpers/ValidationHelper.cs b/WebApi/Helpers/ValidationHelper.cs new file mode 100644 index 0000000..43e3a32 --- /dev/null +++ b/WebApi/Helpers/ValidationHelper.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace WebApi.Helpers +{ + public class ValidationHelper + { + /// + /// 验证对象的必填字段 + /// + /// 要验证的对象类型 + /// 要验证的对象 + /// 错误信息 + /// 验证是否通过 + public static bool ValidateRequired(T obj, out string errorMessage) + { + errorMessage = string.Empty; + if (obj == null) + { + errorMessage = "对象不能为空"; + return false; + } + + var properties = typeof(T).GetProperties(); + foreach (var prop in properties) + { + var value = prop.GetValue(obj); + if (value == null) + { + errorMessage = $"【{prop.Name}不能为空】"; + return false; + } + //else if (prop.PropertyType == typeof(int) && (int)value == 0) + //{ + // errorMessage = $"【{prop.Name}不能为0】"; + // return false; + //} + else if (prop.PropertyType == typeof(string) && string.IsNullOrEmpty((string)value)) + { + errorMessage = $"【{prop.Name}不能为空】"; + return false; + } + else if (prop.PropertyType == typeof(object) && (object)value == null) + { + errorMessage = $"【{prop.Name}不能为空】"; + return false; + } + } + + return true; + } + + /// + /// 验证对象的指定字段 + /// + /// 要验证的对象类型 + /// 要验证的对象 + /// 要验证的属性名列表 + /// 错误信息 + /// 验证是否通过 + public static bool ValidateProperties(T obj, string[] propertyNames, out string errorMessage) + { + errorMessage = string.Empty; + if (obj == null) + { + errorMessage = "对象不能为空"; + return false; + } + + foreach (var propName in propertyNames) + { + var prop = typeof(T).GetProperty(propName); + if (prop == null) continue; + + var value = prop.GetValue(obj); + if (value == null) + { + errorMessage = $"【{propName}不能为空】"; + return false; + } + //else if (prop.PropertyType == typeof(int) && (int)value == 0) + //{ + // errorMessage = $"【{propName}不能为0】"; + // return false; + //} + else if (prop.PropertyType == typeof(string) && string.IsNullOrEmpty((string)value)) + { + errorMessage = $"【{propName}不能为空】"; + return false; + } + } + + return true; + } + } +} \ No newline at end of file diff --git a/WebApi/IFileController.cs b/WebApi/IFileController.cs new file mode 100644 index 0000000..9bb263b --- /dev/null +++ b/WebApi/IFileController.cs @@ -0,0 +1,277 @@ +using System.Net.Http; +using System.Net; +using System.Web.Http; +using Newtonsoft.Json.Linq; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System; + +/////http://127.0.0.1:9981/api/file/browse + +/// +/// +/// +namespace WebApi +{ + /// + /// + /// + [RoutePrefix("api/file")] + public class IFileController : ApiController + { + // 基础路径配置 + private readonly string _basePath = @"D:\项目文件"; + + /// + /// 请求DTO + /// + public class FileRequestDto + { + public string RelativePath { get; set; } = ""; + } + + /// + /// 浏览文件或文件夹,前端传相对路径,返回文件夹内容或文件流(图片等可预览) + /// + [HttpPost] + [Route("browse")] + public IHttpActionResult BrowsePath([FromBody] FileRequestDto request) + { + try + { + if (request == null) + request = new FileRequestDto(); + + if (string.IsNullOrEmpty(request.RelativePath) || request.RelativePath == "/") + { + request.RelativePath = ""; + } + + string fullPath = Path.Combine(_basePath, request.RelativePath.Replace('/', Path.DirectorySeparatorChar)); + + if (!IsPathSafe(fullPath)) + { + return Ok(new { success = false, message = "无效的路径" }); + } + + if (!Directory.Exists(fullPath) && !System.IO.File.Exists(fullPath)) + { + return Ok(new { success = false, message = "路径不存在" }); + } + + if (System.IO.File.Exists(fullPath)) + { + return GetFilePreview(fullPath, request.RelativePath); + } + + if (Directory.Exists(fullPath)) + { + return GetDirectoryContents(fullPath, request.RelativePath); + } + + return Ok(new { success = false, message = "路径不存在" }); + } + catch (Exception ex) + { + return Ok(new { success = false, message = $"服务器错误: {ex.Message}" }); + } + } + + /// + /// 获取文件预览数据(图片/文本base64,前端可直接预览) + /// + private IHttpActionResult GetFilePreview(string fullPath, string relativePath) + { + try + { + var fileInfo = new FileInfo(fullPath); + var extension = fileInfo.Extension.ToLowerInvariant(); + var previewable = IsPreviewableFile(extension); + var contentType = GetContentType(fileInfo.Name); + + bool tooLarge = fileInfo.Length > 10 * 1024 * 1024; // 10MB限制 + string base64String = null; + string dataUrl = null; + bool canPreview = previewable && !tooLarge; + if (canPreview) + { + var fileBytes = System.IO.File.ReadAllBytes(fullPath); + base64String = Convert.ToBase64String(fileBytes); + dataUrl = $"data:{contentType};base64,{base64String}"; + } + + var result = new + { + success = true, + type = "file", + path = relativePath, + name = fileInfo.Name, + size = fileInfo.Length, + extension = fileInfo.Extension, + contentType = contentType, + isPreviewable = canPreview, + base64Data = base64String, + dataUrl = dataUrl, + created = fileInfo.CreationTime, + modified = fileInfo.LastWriteTime, + message = tooLarge ? "文件过大,无法预览,可下载" : null + }; + return Ok(result); + } + catch (Exception ex) + { + return Ok(new { success = false, message = $"获取文件预览失败: {ex.Message}" }); + } + } + + /// + /// 判断文件是否可预览 + /// + private bool IsPreviewableFile(string extension) + { + var previewableExtensions = new[] + { + ".bmp", ".jpg", ".jpeg", ".png", ".gif", ".tiff", ".tif", ".webp", + ".txt", ".json", ".xml", ".csv", ".log", ".md" + }; + return previewableExtensions.Contains(extension); + } + + /// + /// 安全检查:确保路径在基础目录内,防止路径遍历攻击 + /// + private bool IsPathSafe(string fullPath) + { + try + { + var basePath = Path.GetFullPath(_basePath); + var requestedPath = Path.GetFullPath(fullPath); + return requestedPath.StartsWith(basePath, StringComparison.OrdinalIgnoreCase); + } + catch + { + return false; + } + } + + /// + /// 根据文件扩展名获取MIME类型(兼容C# 7.3) + /// + private string GetContentType(string fileName) + { + var extension = Path.GetExtension(fileName).ToLowerInvariant(); + if (extension == ".bmp") return "image/bmp"; + if (extension == ".jpg" || extension == ".jpeg") return "image/jpeg"; + if (extension == ".png") return "image/png"; + if (extension == ".gif") return "image/gif"; + if (extension == ".tiff" || extension == ".tif") return "image/tiff"; + if (extension == ".webp") return "image/webp"; + if (extension == ".pdf") return "application/pdf"; + if (extension == ".txt") return "text/plain"; + if (extension == ".json") return "application/json"; + if (extension == ".xml") return "application/xml"; + if (extension == ".csv") return "text/csv"; + if (extension == ".md") return "text/markdown"; + if (extension == ".log") return "text/plain"; + if (extension == ".zip") return "application/zip"; + if (extension == ".rar") return "application/x-rar-compressed"; + return "application/octet-stream"; + } + + private IHttpActionResult GetDirectoryContents(string fullPath, string relativePath) + { + try + { + var items = new List(); + var directories = Directory.GetDirectories(fullPath); + foreach (var dir in directories) + { + var dirInfo = new DirectoryInfo(dir); + var subPath = string.IsNullOrEmpty(relativePath) + ? dirInfo.Name + : $"{relativePath}/{dirInfo.Name}"; + items.Add(new + { + name = dirInfo.Name, + type = "directory", + path = subPath, + created = dirInfo.CreationTime, + modified = dirInfo.LastWriteTime, + isPreviewable = false + }); + } + var files = Directory.GetFiles(fullPath); + foreach (var file in files) + { + var fileInfo = new FileInfo(file); + var filePath = string.IsNullOrEmpty(relativePath) + ? fileInfo.Name + : $"{relativePath}/{fileInfo.Name}"; + var extension = fileInfo.Extension.ToLowerInvariant(); + items.Add(new + { + name = fileInfo.Name, + type = "file", + path = filePath, + size = fileInfo.Length, + extension = fileInfo.Extension, + created = fileInfo.CreationTime, + modified = fileInfo.LastWriteTime, + isPreviewable = IsPreviewableFile(extension), + contentType = GetContentType(fileInfo.Name) + }); + } + var result = new + { + success = true, + type = "directory", + path = relativePath, + items = items.OrderBy(x => ((dynamic)x).type == "directory" ? 0 : 1) + .ThenBy(x => ((dynamic)x).name) + .ToList() + }; + return Ok(result); + } + catch (Exception ex) + { + return Ok(new { success = false, message = $"读取目录失败: {ex.Message}" }); + } + } + + [HttpPost] + [Route("download")] + public IHttpActionResult DownloadFile([FromBody] FileRequestDto request) + { + try + { + if (request == null || string.IsNullOrEmpty(request.RelativePath)) + return Ok(new { success = false, message = "文件路径不能为空" }); + + string fullPath = Path.Combine(_basePath, request.RelativePath.Replace('/', Path.DirectorySeparatorChar)); + if (!IsPathSafe(fullPath) || !System.IO.File.Exists(fullPath)) + return Ok(new { success = false, message = "文件不存在" }); + + var fileInfo = new FileInfo(fullPath); + var contentType = GetContentType(fileInfo.Name); + + var response = new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new StreamContent(new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.Read)) + }; + response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType); + response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") + { + FileName = fileInfo.Name + }; + return ResponseMessage(response); + } + catch (Exception ex) + { + return Ok(new { success = false, message = $"下载文件失败: {ex.Message}" }); + } + } + } +} + diff --git a/WebApi/IOrderController.cs b/WebApi/IOrderController.cs new file mode 100644 index 0000000..41074e8 --- /dev/null +++ b/WebApi/IOrderController.cs @@ -0,0 +1,81 @@ +using System.Net.Http; +using System.Text; +using System.Web.Http; +using Newtonsoft.Json.Linq; +using System.Threading.Tasks; + +/////http://127.0.0.1:9981/api/IOrder/InsertOrder + +/// +/// +/// +namespace WebApi +{ + /// + /// + /// + [RoutePrefix("api/imes")] + public class imesController : ApiController + { + readonly string headUrl = "api/imes/"; + + [HttpPost] + public HttpResponseMessage TestPost([FromBody] JObject jobj) + { + if (jobj == null) jobj = new JObject(); + return new HttpResponseMessage + { + Content = new StringContent(ServerController.TestPost(headUrl + System.Reflection.MethodBase.GetCurrentMethod().Name, jobj.ToString()), Encoding.GetEncoding("UTF-8"), "application/json") + }; + } + + /// + /// WEB发送请求给WEB API 注意 这是异步操作 + /// + /// + /// + [HttpPost] + public async Task MES_To_AGV_From_WEB([FromBody] JObject jobj) + { + if (jobj == null) jobj = new JObject(); + var result = await ServerController.MES_To_AGV_From_WEB(headUrl + "MES_To_AGV_From_WEB", jobj.ToString()); + return new HttpResponseMessage + { + Content = new StringContent(result, Encoding.GetEncoding("UTF-8"), "application/json") + }; + } + + /// + /// WEB发送请求给WEB API 注意 这是异步操作 + /// 测试版 + /// + /// + /// + [HttpPost] + public async Task MES_To_AGV_From_WEB_Test([FromBody] JObject jobj) + { + if (jobj == null) jobj = new JObject(); + var result = await ServerController.MES_To_AGV_From_WEB_Test(headUrl + "MES_To_AGV_From_WEB_Test", jobj.ToString()); + return new HttpResponseMessage + { + Content = new StringContent(result, Encoding.GetEncoding("UTF-8"), "application/json") + }; + } + + /// + /// AGV与MES站点交互 + /// + /// + /// + [HttpPost] + public async Task AGV_To_MES_AgvPass([FromBody] JObject jobj) + { + if (jobj == null) jobj = new JObject(); + var result = await ServerController.AGV_To_MES_AgvPass(headUrl + "AGV_To_MES_AgvPass", jobj.ToString()); + return new HttpResponseMessage + { + Content = new StringContent(result, Encoding.GetEncoding("UTF-8"), "application/json") + }; + } + } +} diff --git a/WebApi/InitServer.cs b/WebApi/InitServer.cs new file mode 100644 index 0000000..f75cc7b --- /dev/null +++ b/WebApi/InitServer.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Net.Http.Formatting; +using System.Net.Http.Headers; +using System.Text; +using System.Web.Http; +using System.Web.Http.Cors; +using System.Web.Http.SelfHost; + +namespace WebApi +{ + /// + /// + /// + public class InitServer + { + /// + /// + /// + HttpSelfHostConfiguration config = null; + /// + /// + /// + HttpSelfHostServer server = null; + /// + /// + /// + /// + public InitServer(int port) + { + config = new HttpSelfHostConfiguration($"http://0.0.0.0:{port}"); + + config.EnableCors(new EnableCorsAttribute("*", "*", "*")); + + config.MapHttpAttributeRoutes(); + + //config.Routes.MapHttpRoute( + // name: "DefaultApi", + // routeTemplate: "api/{controller}/{id}", + // defaults: new { id = RouteParameter.Optional } + //); + + // 自定义路由匹配到action + config.Routes.MapHttpRoute( + name: "API Default", + routeTemplate: "api/{controller}/{action}/{id}", + defaults: new { id = RouteParameter.Optional } + ); + server = new HttpSelfHostServer(config); + + server.OpenAsync().Wait(); + + } + + public void Close() + { + server.CloseAsync(); + } + /// + /// + /// + public class JsonContentNegotiator : IContentNegotiator + { + /// + /// + /// + private readonly JsonMediaTypeFormatter _jsonFormatter; + /// + /// + /// + /// + public JsonContentNegotiator(JsonMediaTypeFormatter formatter) + { + _jsonFormatter = formatter; + } + /// + /// + /// + /// + /// + /// + /// + public ContentNegotiationResult Negotiate(Type type, HttpRequestMessage request, IEnumerable formatters) + { + var result = new ContentNegotiationResult(_jsonFormatter, new MediaTypeHeaderValue("application/json")); + return result; + } + + public static string Postring1(string url, string token, Dictionary dic) + { + string results = ""; + //url = "http://172.16.22.15:8000/" + url; + + HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); + req.Method = "POST"; + req.ContentType = "application/x-www-form-urlencoded"; + req.Headers.Add("Authorization", "Bearer " + token); + + StringBuilder builder = new StringBuilder(); + int i = 0; + foreach (var item in dic) + { + if (i > 0) + builder.Append("&"); + builder.AppendFormat("{0}={1}", item.Key, item.Value); + i++; + } + byte[] data = Encoding.UTF8.GetBytes(builder.ToString()); + req.ContentLength = data.Length; + try + { + using (Stream reqStream = req.GetRequestStream()) + { + reqStream.Write(data, 0, data.Length); + reqStream.Close(); + } + HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); + Stream stream = resp.GetResponseStream(); + //获取响应内容 + using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) + { + results = reader.ReadToEnd(); + } + return results; + } + catch (Exception e) + { + Console.WriteLine(e.Message); + return e.Message; + throw; + } + + } + + + + } + } +} diff --git a/WebApi/Models/AGV_To_MES_AgvArrive_Req.cs b/WebApi/Models/AGV_To_MES_AgvArrive_Req.cs new file mode 100644 index 0000000..944fa68 --- /dev/null +++ b/WebApi/Models/AGV_To_MES_AgvArrive_Req.cs @@ -0,0 +1,33 @@ + +using System; + +namespace WebApi.Models +{ + public class AGV_To_MES_AgvArrive_Req + { + /// + /// 任务号 唯一ID + /// + public string taskId + { + get; + set; + } + /// + /// 工位号 + /// + public string station + { + get; + set; + } + /// + /// AGV编号 + /// + public int agvNum + { + get; + set; + } + } +} diff --git a/WebApi/Models/AGV_To_MES_AgvMateria_Req.cs b/WebApi/Models/AGV_To_MES_AgvMateria_Req.cs new file mode 100644 index 0000000..2efda6d --- /dev/null +++ b/WebApi/Models/AGV_To_MES_AgvMateria_Req.cs @@ -0,0 +1,89 @@ + +using System; + +namespace WebApi.Models +{ + public class AGV_To_MES_AgvMateria_Req + { + /// + /// 任务号 唯一ID + /// + public string taskId + { + get; + set; + } + /// + /// 客户端 固定值agv + /// + public string clientId + { + get; + set; + } + /// + /// 任务类型 0叫料,1送料,2叫空托,3送空托,4点对点,5退料 + /// + public int taskType + { + get; + set; + } + /// + /// 任务状态 3任务取消 21取货完成 23 放完 + /// + public int status + { + get; + set; + } + /// + /// 取料点 taskType为1,3,4时必填 + /// + public string pickStock + { + get; + set; + } + /// + /// 放料点 taskType为0,2,4时必填 + /// + public string dropStock + { + get; + set; + } + /// + /// 托盘号 + /// + public string palletId + { + get; + set; + } + /// + /// 物料号 物料编码(叫料时必填) + /// + public string materialId + { + get; + set; + } + /// + /// 需求数量 + /// + public int requireNum + { + get; + set; + } + /// + /// 下发时间 + /// + public string createTime + { + get; + set; + } + } +} diff --git a/WebApi/Models/AGV_To_MES_AgvPass_Req.cs b/WebApi/Models/AGV_To_MES_AgvPass_Req.cs new file mode 100644 index 0000000..2d41c88 --- /dev/null +++ b/WebApi/Models/AGV_To_MES_AgvPass_Req.cs @@ -0,0 +1,65 @@ + +using System; + +namespace WebApi.Models +{ + public class AGV_To_MES_AgvPass_Req + { + /// + /// 任务号 唯一ID + /// + public string taskId + { + get; + set; + } + /// + /// 工位号 + /// + public string station + { + get; + set; + } + /// + /// 0到位,1离开 + /// + public int type + { + get; + set; + } + /// + /// AGV编号 + /// + public int agvNum + { + get; + set; + } + /// + /// 总成编号 + /// + public string EngineNo + { + get; + set; + } + /// + /// 订单号 + /// + public string OrderNo + { + get; + set; + } + /// + /// 机型号 + /// + public string SortNo + { + get; + set; + } + } +} diff --git a/WebApi/Models/msgResHeader.cs b/WebApi/Models/msgResHeader.cs new file mode 100644 index 0000000..4e774fd --- /dev/null +++ b/WebApi/Models/msgResHeader.cs @@ -0,0 +1,31 @@ + +namespace WebApi.Models +{ + public class msgResHeader + { + /// + /// 返回结果 bool + /// + public bool Result + { + get; + set; + } + /// + /// 返回消息 + /// + public string ErrMsg + { + get; + set; + } + /// + /// 返回结果集 + /// + public object Data + { + get; + set; + } + } +} diff --git a/WebApi/Models/test.cs b/WebApi/Models/test.cs new file mode 100644 index 0000000..1df8ad3 --- /dev/null +++ b/WebApi/Models/test.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WebApi.Models +{ + public class test + { + public string msg + { + get; + set; + } + + public int code + { + get; + set; + } + } +} diff --git a/WebApi/ServerController.cs b/WebApi/ServerController.cs new file mode 100644 index 0000000..a1922e0 --- /dev/null +++ b/WebApi/ServerController.cs @@ -0,0 +1,418 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Data; +using WebApi.Models; +using WebApi.Helpers; +using System.Reflection; +using Logger; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace WebApi +{ + public class ServerController + { + private static readonly HttpClient httpClient; + public static event Action ShowMsg; // 记录日志事件 + + static ServerController() + { + httpClient = new HttpClient(); + httpClient.Timeout = TimeSpan.FromSeconds(20); // 设置超时时间为20秒 + } + + /// + /// UUID生成 + /// + /// + public static string UuidUtil() + { + string result = Guid.NewGuid().ToString(); + return result; + } + + public static int SaveWebApiReqLogo(string url, string JSON) + { + int AID = -1; + try + { + //存储日志 + var CreateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); + var param = new Dictionary{ + { "接口地址", url }, + { "接口类型", 2 }, + { "请求内容", JSON }, + { "请求时间", CreateTime } + }; + SqlServer.ExecuteProcedure("接口_IOT接口交互日志_请求记录", param, out DataTable dt, out string err); + if (dt.Rows.Count > 0) + { + AID = Convert.ToInt32(dt.Rows[0]["AID"]); + } + } + catch (Exception ex) + { + Log.FunError(ex, MethodBase.GetCurrentMethod().Name); + } + return AID; + } + + public static int SaveWebApiResLogo(int AID, string JSON) + { + try + { + + //new SqlParameter("@AID",AID), + //new SqlParameter("@响应时间",CreateTime), + //new SqlParameter("@响应内容",JsonConvert.SerializeObject(result)) + + //存储日志 + var CreateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); + var param = new Dictionary{ + { "AID", AID }, + { "响应时间", CreateTime }, + { "响应内容", JSON }, + }; + SqlServer.ExecuteProcedure("接口_IOT接口交互日志_响应记录", param, out DataTable dt, out string err); + if (dt.Rows.Count > 0) + { + AID = Convert.ToInt32(dt.Rows[0]["AID"]); + } + } + catch (Exception ex) + { + Log.FunError(ex, MethodBase.GetCurrentMethod().Name); + } + return AID; + } + + /// + /// 测试标准接口方法 + /// + /// + /// + /// + public static string TestPost(string url, string json) + { + var result = new msgResHeader(); + //result.taskId = UuidUtil(); + result.Result = false; + result.ErrMsg = ""; + result.Data = ""; + + string errorMessage = ""; + int AID = -1; + try + { + AID = SaveWebApiReqLogo(url, json); + + // 解析订单内容,存储数据库,根据实际业务来写 + test personnelBaseData = JsonConvert.DeserializeObject(json); + ShowMsg?.Invoke("【" + url + "】code" + personnelBaseData.code + ",msg:" + personnelBaseData.msg); + //result.msg = errorMessage; + + AID = SaveWebApiResLogo(AID, JsonConvert.SerializeObject(result)); + } + catch (Exception err) + { + result.Result = false; + result.ErrMsg = err.Message; + result.Data = "ERROR"; + Log.FunError(err, MethodBase.GetCurrentMethod().Name); + } + + return JsonConvert.SerializeObject(result); + } + + /// + /// 前端对AGV通用的接口转发 + /// + /// + /// + /// + public static async Task MES_To_AGV_From_WEB(string url, string json) + { + var result = new msgResHeader(); + result.Result = false; + result.ErrMsg = ""; + result.Data = ""; + + string errorMessage = ""; + int AID = -1; + try + { + // 显示一下接口日志 + ShowMsg?.Invoke("Receive【" + url + "】" + json); + AID = SaveWebApiReqLogo(url, json); + + MES_To_AGV_From_WEB_Req personnelBaseData = JsonConvert.DeserializeObject(json); + // 验证必填字段 + if (!ValidationHelper.ValidateRequired(personnelBaseData, out errorMessage)) + { + ShowMsg?.Invoke($"****************{errorMessage}"); + result.ErrMsg = errorMessage; + return JsonConvert.SerializeObject(result); + } + + string AGVApiBaseUrl = Tools.AppConfigManage.ReadConfig("AGVApiBaseUrl"); + string AGVIP = Tools.AppConfigManage.ReadConfig("AGVIP"); + string AGVApiUrl = "http://" + AGVIP + AGVApiBaseUrl + personnelBaseData.url; + + // 发送POST请求 + var content = new StringContent( + JsonConvert.SerializeObject(personnelBaseData.data), + Encoding.UTF8, + "application/json" + ); + + var response = await httpClient.PostAsync(AGVApiUrl, content); + var responseContent = await response.Content.ReadAsStringAsync(); + + if (response.IsSuccessStatusCode) + { + result.Result = true; + result.Data = responseContent; + } + else + { + result.Result = false; + result.ErrMsg = $"请求失败: {response.StatusCode} - {responseContent}"; + } + + AID = SaveWebApiResLogo(AID, JsonConvert.SerializeObject(result)); + } + catch (TaskCanceledException ex) + { + if (!ex.CancellationToken.IsCancellationRequested) + { + ShowMsg?.Invoke("请求超时,请检查目标服务是否可达或响应过慢!"); + result.ErrMsg = "请求超时,请检查目标服务是否可达或响应过慢!"; + } + else + { + ShowMsg?.Invoke("请求被主动取消!"); + result.ErrMsg = "请求被主动取消!"; + } + result.Data = "ERROR"; + Log.FunError(ex, MethodBase.GetCurrentMethod().Name); + } + catch (Exception err) + { + result.Result = false; + result.ErrMsg = err.Message; + result.Data = "ERROR"; + Log.FunError(err, MethodBase.GetCurrentMethod().Name); + } + + return JsonConvert.SerializeObject(result); + } + + /// + /// 前端对AGV通用的接口转发 + /// 测试版 + /// + /// + /// + /// + public static async Task MES_To_AGV_From_WEB_Test(string url, string json) + { + var result = new msgResHeader(); + result.Result = false; + result.ErrMsg = ""; + result.Data = ""; + + string errorMessage = ""; + int AID = -1; + try + { + // 显示一下接口日志 + ShowMsg?.Invoke("Receive【" + url + "】" + json); + AID = SaveWebApiReqLogo(url, json); + + var result2 = new msgResHeader(); + result2.Result = true; + result2.ErrMsg = ""; + result2.Data = ""; + + MES_To_AGV_From_WEB_Req personnelBaseData = JsonConvert.DeserializeObject(json); + // 验证必填字段 + if (!ValidationHelper.ValidateRequired(personnelBaseData, out errorMessage)) + { + ShowMsg?.Invoke($"****************{errorMessage}"); + result.ErrMsg = errorMessage; + return JsonConvert.SerializeObject(result); + } + + // 手动模拟 + // 接口1 库区列表查询 返回固定JSON数据 + if(personnelBaseData.url == "getPartitionList") + { + var partitionList = new List + { + new { PartitionCode = "1", PartitionName = "隔离开关操作试验区" }, + new { PartitionCode = "2", PartitionName = "断路器线边缓存位" }, + new { PartitionCode = "3", PartitionName = "CT装配区" }, + new { PartitionCode = "4", PartitionName = "断路器下线" }, + new { PartitionCode = "5", PartitionName = "OP30产线工位" }, + new { PartitionCode = "6", PartitionName = "线边缓存库" }, + new { PartitionCode = "7", PartitionName = "断路器试验区" }, + new { PartitionCode = "8", PartitionName = "隔离开关安装操作缓存区" }, + new { PartitionCode = "9", PartitionName = "隔离开关下线" }, + new { PartitionCode = "10", PartitionName = "断路器缓存区" }, + new { PartitionCode = "11", PartitionName = "OP20产线工位" }, + new { PartitionCode = "12", PartitionName = "OP10产线工位" } + }; + result.Result = true; + result2.Data = partitionList; + result.Data = JsonConvert.SerializeObject(result2); + } + + // 接口2 库位列表查询 返回固定JSON数据 + if(personnelBaseData.url == "getStockList") + { + var stockList = new List + { + // StockCode 库位编号 + // StockName 库位名称 + // StockStatus 满料状态 bool + // PalletCode 托盘编号 + // EngineNo 产品编号 + // SortNo 产品型号 + // TaskId 任务号 + + new { StockCode = "6", StockName = "工位线边缓存位1", StockStatus = true, PalletCode = "pallTestCode1", EngineNo = "GCBTest01", SortNo = "P7223814G003", TaskId = "12312" }, + new { StockCode = "16", StockName = "工位线边缓存位2", StockStatus = true, PalletCode = "pallTestCode2", EngineNo = "CTTest01-1", SortNo = "P7223363G001", TaskId = (string)null }, + new { StockCode = "30", StockName = "工位线边缓存位3", StockStatus = false, PalletCode = "pallTestCode3", EngineNo = (string)null, SortNo = (string)null, TaskId = (string)null }, + new { StockCode = "2", StockName = "工位线边缓存位4", StockStatus = false, PalletCode = (string)null, EngineNo = (string)null, SortNo = (string)null, TaskId = (string)null }, + }; + result.Result = true; + result2.Data = stockList; + result.Data = JsonConvert.SerializeObject(result2); + + } + + // 接口3 更新库位信息 + if (personnelBaseData.url == "updateStockInfo") + { + result.Result = true; + result.Data = JsonConvert.SerializeObject(result2); + } + + // 接口4 创建送料任务 + if (personnelBaseData.url == "createTask") + { + result.Result = true; + result.Data = JsonConvert.SerializeObject(result2); + } + + AID = SaveWebApiResLogo(AID, JsonConvert.SerializeObject(result)); + } + catch (TaskCanceledException ex) + { + if (!ex.CancellationToken.IsCancellationRequested) + { + ShowMsg?.Invoke("请求超时,请检查目标服务是否可达或响应过慢!"); + result.ErrMsg = "请求超时,请检查目标服务是否可达或响应过慢!"; + } + else + { + ShowMsg?.Invoke("请求被主动取消!"); + result.ErrMsg = "请求被主动取消!"; + } + result.Data = "ERROR"; + Log.FunError(ex, MethodBase.GetCurrentMethod().Name); + } + catch (Exception err) + { + result.Result = false; + result.ErrMsg = err.Message; + result.Data = "ERROR"; + Log.FunError(err, MethodBase.GetCurrentMethod().Name); + } + + return JsonConvert.SerializeObject(result); + } + + /// + /// AGV到位,离开 + /// + /// + /// + /// + public static async Task AGV_To_MES_AgvPass(string url, string json) + { + var result = new msgResHeader(); + result.Result = false; + result.ErrMsg = ""; + result.Data = ""; + + string errorMessage = ""; + int AID = -1; + try + { + // 显示一下接口日志 + ShowMsg?.Invoke("Receive【" + url + "】" + json); + AID = SaveWebApiReqLogo(url, json); + + // 解析订单内容,存储数据库,根据实际业务来写 + AGV_To_MES_AgvPass_Req personnelBaseData = JsonConvert.DeserializeObject(json); + + // 验证必填字段 + if (!ValidationHelper.ValidateRequired(personnelBaseData, out errorMessage)) + { + ShowMsg?.Invoke($"****************{errorMessage}"); + result.ErrMsg = errorMessage; + return JsonConvert.SerializeObject(result); + } + + + int workOverType = 0; + if (personnelBaseData.type == 0) + { + workOverType = 1; + } + else if (personnelBaseData.type == 1) + { + workOverType = 3; + } + else + { + ShowMsg?.Invoke($"****************未识别的type{workOverType}"); + result.ErrMsg = $"未识别的Type{workOverType}"; + return JsonConvert.SerializeObject(result); + } + + var param = new Dictionary{ + { "工位号", personnelBaseData.station }, + { "任务编号", personnelBaseData.taskId }, + { "工件编号", personnelBaseData.EngineNo }, + { "type", workOverType}, + }; + SqlServer.ExecuteProcedure("PTCHV_AGV_进离站", param, out DataTable dt, out errorMessage); + // 验证必填字段 + if (errorMessage.Length > 0) + { + ShowMsg?.Invoke($"****************{errorMessage}"); + result.ErrMsg = errorMessage; + return JsonConvert.SerializeObject(result); + } + + await MqttServer.SendMqttMessageToOp(personnelBaseData.station, "AGVStatus", workOverType.ToString()); + + result.Result = true; + AID = SaveWebApiResLogo(AID, JsonConvert.SerializeObject(result)); + } + catch (Exception err) + { + result.Result = false; + result.ErrMsg = err.Message; + result.Data = "ERROR"; + Log.FunError(err, MethodBase.GetCurrentMethod().Name); + } + + return JsonConvert.SerializeObject(result); + } + } +} diff --git a/icon/002_列表.png b/icon/002_列表.png new file mode 100644 index 0000000..81abc65 Binary files /dev/null and b/icon/002_列表.png differ diff --git a/icon/0780fca3def52d8a02649c7aa2f8093a.gif b/icon/0780fca3def52d8a02649c7aa2f8093a.gif new file mode 100644 index 0000000..f27d4fa Binary files /dev/null and b/icon/0780fca3def52d8a02649c7aa2f8093a.gif differ diff --git a/icon/BOSS-数据管理.ico b/icon/BOSS-数据管理.ico new file mode 100644 index 0000000..0cda236 Binary files /dev/null and b/icon/BOSS-数据管理.ico differ diff --git a/icon/BOSS-数据管理.png b/icon/BOSS-数据管理.png new file mode 100644 index 0000000..eca58d7 Binary files /dev/null and b/icon/BOSS-数据管理.png differ diff --git a/icon/HMI.png b/icon/HMI.png new file mode 100644 index 0000000..c059b57 Binary files /dev/null and b/icon/HMI.png differ diff --git a/icon/JD.png b/icon/JD.png new file mode 100644 index 0000000..abe9aa8 Binary files /dev/null and b/icon/JD.png differ diff --git a/icon/MBE风格多色图标-密码.png b/icon/MBE风格多色图标-密码.png new file mode 100644 index 0000000..e20eaa8 Binary files /dev/null and b/icon/MBE风格多色图标-密码.png differ diff --git a/icon/Mes32X32.ico b/icon/Mes32X32.ico new file mode 100644 index 0000000..ec465b2 Binary files /dev/null and b/icon/Mes32X32.ico differ diff --git a/icon/action_Cancel_16xLG.png b/icon/action_Cancel_16xLG.png new file mode 100644 index 0000000..ac08d59 Binary files /dev/null and b/icon/action_Cancel_16xLG.png differ diff --git a/icon/bitbug_favicon.ico b/icon/bitbug_favicon.ico new file mode 100644 index 0000000..4e9b14c Binary files /dev/null and b/icon/bitbug_favicon.ico differ diff --git a/icon/excelICON.ico b/icon/excelICON.ico new file mode 100644 index 0000000..f7dcbf6 Binary files /dev/null and b/icon/excelICON.ico differ diff --git a/icon/jk.ico b/icon/jk.ico new file mode 100644 index 0000000..fe585a8 Binary files /dev/null and b/icon/jk.ico differ diff --git a/icon/panlClose.png b/icon/panlClose.png new file mode 100644 index 0000000..462a22f Binary files /dev/null and b/icon/panlClose.png differ diff --git a/icon/ssbj.png b/icon/ssbj.png new file mode 100644 index 0000000..10dc152 Binary files /dev/null and b/icon/ssbj.png differ diff --git a/icon/staticjd.png b/icon/staticjd.png new file mode 100644 index 0000000..f891867 Binary files /dev/null and b/icon/staticjd.png differ diff --git a/icon/上传.png b/icon/上传.png new file mode 100644 index 0000000..6716d20 Binary files /dev/null and b/icon/上传.png differ diff --git a/icon/上载.jpg b/icon/上载.jpg new file mode 100644 index 0000000..344b17d Binary files /dev/null and b/icon/上载.jpg differ diff --git a/icon/下载.png b/icon/下载.png new file mode 100644 index 0000000..6122e35 Binary files /dev/null and b/icon/下载.png differ diff --git a/icon/业务.png b/icon/业务.png new file mode 100644 index 0000000..f0adf1d Binary files /dev/null and b/icon/业务.png differ diff --git a/icon/任务监控和查询.png b/icon/任务监控和查询.png new file mode 100644 index 0000000..ff8cca0 Binary files /dev/null and b/icon/任务监控和查询.png differ diff --git a/icon/保存.png b/icon/保存.png new file mode 100644 index 0000000..97bd4dd Binary files /dev/null and b/icon/保存.png differ diff --git a/icon/信息_记录.png b/icon/信息_记录.png new file mode 100644 index 0000000..e92f9b7 Binary files /dev/null and b/icon/信息_记录.png differ diff --git a/icon/关闭.png b/icon/关闭.png new file mode 100644 index 0000000..b78aef6 Binary files /dev/null and b/icon/关闭.png differ diff --git a/icon/关闭系统.png b/icon/关闭系统.png new file mode 100644 index 0000000..ffd64a8 Binary files /dev/null and b/icon/关闭系统.png differ diff --git a/icon/写入托盘.jpg b/icon/写入托盘.jpg new file mode 100644 index 0000000..1a209b9 Binary files /dev/null and b/icon/写入托盘.jpg differ diff --git a/icon/分布图.ico b/icon/分布图.ico new file mode 100644 index 0000000..d2bd021 Binary files /dev/null and b/icon/分布图.ico differ diff --git a/icon/分布图.png b/icon/分布图.png new file mode 100644 index 0000000..c41710c Binary files /dev/null and b/icon/分布图.png differ diff --git a/icon/列表.png b/icon/列表.png new file mode 100644 index 0000000..95df08c Binary files /dev/null and b/icon/列表.png differ diff --git a/icon/列表2.png b/icon/列表2.png new file mode 100644 index 0000000..375743f Binary files /dev/null and b/icon/列表2.png differ diff --git a/icon/删除.png b/icon/删除.png new file mode 100644 index 0000000..76903f0 Binary files /dev/null and b/icon/删除.png differ diff --git a/icon/刷新.png b/icon/刷新.png new file mode 100644 index 0000000..98bf964 Binary files /dev/null and b/icon/刷新.png differ diff --git a/icon/动态数据查询.png b/icon/动态数据查询.png new file mode 100644 index 0000000..ad87d56 Binary files /dev/null and b/icon/动态数据查询.png differ diff --git a/icon/合作.png b/icon/合作.png new file mode 100644 index 0000000..973f7ea Binary files /dev/null and b/icon/合作.png differ diff --git a/icon/图表_柱.png b/icon/图表_柱.png new file mode 100644 index 0000000..45d1aad Binary files /dev/null and b/icon/图表_柱.png differ diff --git a/icon/图表_线_通用_统计.png b/icon/图表_线_通用_统计.png new file mode 100644 index 0000000..c39b497 Binary files /dev/null and b/icon/图表_线_通用_统计.png differ diff --git a/icon/图表_饼.png b/icon/图表_饼.png new file mode 100644 index 0000000..ced794d Binary files /dev/null and b/icon/图表_饼.png differ diff --git a/icon/增加.png b/icon/增加.png new file mode 100644 index 0000000..4bfbb6b Binary files /dev/null and b/icon/增加.png differ diff --git a/icon/备份_复制.png b/icon/备份_复制.png new file mode 100644 index 0000000..9159178 Binary files /dev/null and b/icon/备份_复制.png differ diff --git a/icon/审核_盖章.png b/icon/审核_盖章.png new file mode 100644 index 0000000..b0af2d4 Binary files /dev/null and b/icon/审核_盖章.png differ diff --git a/icon/密码.png b/icon/密码.png new file mode 100644 index 0000000..5ddf103 Binary files /dev/null and b/icon/密码.png differ diff --git a/icon/导入.png b/icon/导入.png new file mode 100644 index 0000000..95fd37f Binary files /dev/null and b/icon/导入.png differ diff --git a/icon/导出.png b/icon/导出.png new file mode 100644 index 0000000..aad5f54 Binary files /dev/null and b/icon/导出.png differ diff --git a/icon/工作台.png b/icon/工作台.png new file mode 100644 index 0000000..4d3ec97 Binary files /dev/null and b/icon/工作台.png differ diff --git a/icon/工具.png b/icon/工具.png new file mode 100644 index 0000000..7383324 Binary files /dev/null and b/icon/工具.png differ diff --git a/icon/布局图.png b/icon/布局图.png new file mode 100644 index 0000000..7d2ff19 Binary files /dev/null and b/icon/布局图.png differ diff --git a/icon/帮助.png b/icon/帮助.png new file mode 100644 index 0000000..b2d7d6b Binary files /dev/null and b/icon/帮助.png differ diff --git a/icon/异常_危险.png b/icon/异常_危险.png new file mode 100644 index 0000000..66bc688 Binary files /dev/null and b/icon/异常_危险.png differ diff --git a/icon/手动打印.png b/icon/手动打印.png new file mode 100644 index 0000000..a682191 Binary files /dev/null and b/icon/手动打印.png differ diff --git a/icon/打印机.png b/icon/打印机.png new file mode 100644 index 0000000..721dbc2 Binary files /dev/null and b/icon/打印机.png differ diff --git a/icon/按键分割线.png b/icon/按键分割线.png new file mode 100644 index 0000000..f54e139 Binary files /dev/null and b/icon/按键分割线.png differ diff --git a/icon/按键分割线浅.png b/icon/按键分割线浅.png new file mode 100644 index 0000000..db55df6 Binary files /dev/null and b/icon/按键分割线浅.png differ diff --git a/icon/搜索.png b/icon/搜索.png new file mode 100644 index 0000000..2b2bbc1 Binary files /dev/null and b/icon/搜索.png differ diff --git a/icon/操作管理.jpg b/icon/操作管理.jpg new file mode 100644 index 0000000..c2f4487 Binary files /dev/null and b/icon/操作管理.jpg differ diff --git a/icon/文档.png b/icon/文档.png new file mode 100644 index 0000000..781a0b5 Binary files /dev/null and b/icon/文档.png differ diff --git a/icon/断开.png b/icon/断开.png new file mode 100644 index 0000000..fe5b4e9 Binary files /dev/null and b/icon/断开.png differ diff --git a/icon/断开状态.png b/icon/断开状态.png new file mode 100644 index 0000000..0ae6189 Binary files /dev/null and b/icon/断开状态.png differ diff --git a/icon/断开连接.png b/icon/断开连接.png new file mode 100644 index 0000000..8221ffc Binary files /dev/null and b/icon/断开连接.png differ diff --git a/icon/新增_添加.png b/icon/新增_添加.png new file mode 100644 index 0000000..2ad22a8 Binary files /dev/null and b/icon/新增_添加.png differ diff --git a/icon/日志.ico b/icon/日志.ico new file mode 100644 index 0000000..37a300e Binary files /dev/null and b/icon/日志.ico differ diff --git a/icon/日志.png b/icon/日志.png new file mode 100644 index 0000000..1ef853f Binary files /dev/null and b/icon/日志.png differ diff --git a/icon/更多.png b/icon/更多.png new file mode 100644 index 0000000..eb498c7 Binary files /dev/null and b/icon/更多.png differ diff --git a/icon/权限角色管理.png b/icon/权限角色管理.png new file mode 100644 index 0000000..8ab50e8 Binary files /dev/null and b/icon/权限角色管理.png differ diff --git a/icon/正确_成功.png b/icon/正确_成功.png new file mode 100644 index 0000000..cd1e12d Binary files /dev/null and b/icon/正确_成功.png differ diff --git a/icon/添加.png b/icon/添加.png new file mode 100644 index 0000000..47b1193 Binary files /dev/null and b/icon/添加.png differ diff --git a/icon/用户_账号_我的.png b/icon/用户_账号_我的.png new file mode 100644 index 0000000..5768093 Binary files /dev/null and b/icon/用户_账号_我的.png differ diff --git a/icon/用户_账号_我的_未登录.png b/icon/用户_账号_我的_未登录.png new file mode 100644 index 0000000..bf2ce2f Binary files /dev/null and b/icon/用户_账号_我的_未登录.png differ diff --git a/icon/登出2.jpg b/icon/登出2.jpg new file mode 100644 index 0000000..23ab445 Binary files /dev/null and b/icon/登出2.jpg differ diff --git a/icon/登录.png b/icon/登录.png new file mode 100644 index 0000000..f7b6826 Binary files /dev/null and b/icon/登录.png differ diff --git a/icon/筛选.png b/icon/筛选.png new file mode 100644 index 0000000..ac98854 Binary files /dev/null and b/icon/筛选.png differ diff --git a/icon/系统管理.png b/icon/系统管理.png new file mode 100644 index 0000000..136f392 Binary files /dev/null and b/icon/系统管理.png differ diff --git a/icon/系统管理和监控服务.png b/icon/系统管理和监控服务.png new file mode 100644 index 0000000..dab233f Binary files /dev/null and b/icon/系统管理和监控服务.png differ diff --git a/icon/组群_角色.png b/icon/组群_角色.png new file mode 100644 index 0000000..8e63df3 Binary files /dev/null and b/icon/组群_角色.png differ diff --git a/icon/编辑_修改.png b/icon/编辑_修改.png new file mode 100644 index 0000000..a79662a Binary files /dev/null and b/icon/编辑_修改.png differ diff --git a/icon/解锁.png b/icon/解锁.png new file mode 100644 index 0000000..49f2ed1 Binary files /dev/null and b/icon/解锁.png differ diff --git a/icon/记录2.png b/icon/记录2.png new file mode 100644 index 0000000..04674da Binary files /dev/null and b/icon/记录2.png differ diff --git a/icon/质控管理.png b/icon/质控管理.png new file mode 100644 index 0000000..ad6a993 Binary files /dev/null and b/icon/质控管理.png differ diff --git a/icon/辅助_协助.png b/icon/辅助_协助.png new file mode 100644 index 0000000..d96cb7b Binary files /dev/null and b/icon/辅助_协助.png differ diff --git a/icon/返回2.png b/icon/返回2.png new file mode 100644 index 0000000..4978687 Binary files /dev/null and b/icon/返回2.png differ diff --git a/icon/进度_沙漏.png b/icon/进度_沙漏.png new file mode 100644 index 0000000..87831fb Binary files /dev/null and b/icon/进度_沙漏.png differ diff --git a/icon/连接.png b/icon/连接.png new file mode 100644 index 0000000..cc7650b Binary files /dev/null and b/icon/连接.png differ diff --git a/icon/连接状态.png b/icon/连接状态.png new file mode 100644 index 0000000..ae8e8a1 Binary files /dev/null and b/icon/连接状态.png differ diff --git a/icon/退出.png b/icon/退出.png new file mode 100644 index 0000000..ca2cb38 Binary files /dev/null and b/icon/退出.png differ diff --git a/icon/配置.ico b/icon/配置.ico new file mode 100644 index 0000000..d028cc1 Binary files /dev/null and b/icon/配置.ico differ diff --git a/icon/配置.png b/icon/配置.png new file mode 100644 index 0000000..e16ab0b Binary files /dev/null and b/icon/配置.png differ diff --git a/icon/配置2.ico b/icon/配置2.ico new file mode 100644 index 0000000..45b4c44 Binary files /dev/null and b/icon/配置2.ico differ diff --git a/icon/配置2.png b/icon/配置2.png new file mode 100644 index 0000000..e5e7dc5 Binary files /dev/null and b/icon/配置2.png differ diff --git a/icon/重新加载数据.png b/icon/重新加载数据.png new file mode 100644 index 0000000..c98d847 Binary files /dev/null and b/icon/重新加载数据.png differ diff --git a/icon/锁定.png b/icon/锁定.png new file mode 100644 index 0000000..df62914 Binary files /dev/null and b/icon/锁定.png differ diff --git a/icon/错误_失败.png b/icon/错误_失败.png new file mode 100644 index 0000000..3b56a32 Binary files /dev/null and b/icon/错误_失败.png differ diff --git a/icon/零件管理.jpg b/icon/零件管理.jpg new file mode 100644 index 0000000..44e6676 Binary files /dev/null and b/icon/零件管理.jpg differ diff --git a/packages.config b/packages.config new file mode 100644 index 0000000..0960931 --- /dev/null +++ b/packages.config @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file