refactor: 插件 UI 从 WinForms 迁移到 CycleGUI,并修复代码质量问题
将 StandardScene 各插件的配置/监控窗体从 WinForms 迁移到 CycleGUI(删除 .Designer.cs/.resx,重写为 PanelBuilder 立即模式 UI,新增 CycleUiHelper 统一对话框)。 同时修复代码审核中的问题: - 后台文件写入加锁 + try/catch(ButtonBoxManager / DoorManager,对齐 LoopViewer.SaveTasks 模式) - CoderFieldsMetadata.cs 启用 #nullable enable,消除 CS8632 警告 - DummyCar 移除已废弃的 rightClickAction()/SetPosition() - CarRemoteHelper.OpenVehicleWebPage 的 Process.Start 加 try/catch - 重命名名不副实的 Mstsc()(现为打开网页) - 统一弃元命名为 _ - TrafficInterlockViewer 改用稳定 Id(GUID)做选择/编辑,替代行索引 - csproj 改用 $(CGUILibDir) 解析 CycleGUI,绝对路径收敛到 Directory.Build.props 构建:dotnet build StandardScene.sln → 0 错误,30 警告(均为历史遗留)。 注:static 单例状态重构(审核第 8 项)暂未处理,留待单独任务。
This commit is contained in:
@@ -1,596 +0,0 @@
|
||||
namespace StandardScene.Charge
|
||||
{
|
||||
partial class AlarmConfigManagementForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle4 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
this.splitContainer = new System.Windows.Forms.SplitContainer();
|
||||
this.pnlList = new System.Windows.Forms.Panel();
|
||||
this.dgvAlarmConfigs = new System.Windows.Forms.DataGridView();
|
||||
this.pnlListButtons = new System.Windows.Forms.Panel();
|
||||
this.lblStatistics = new System.Windows.Forms.Label();
|
||||
this.btnClose = new System.Windows.Forms.Button();
|
||||
this.btnRefresh = new System.Windows.Forms.Button();
|
||||
this.pnlSearch = new System.Windows.Forms.Panel();
|
||||
this.cmbLevelFilter = new System.Windows.Forms.ComboBox();
|
||||
this.lblLevelFilter = new System.Windows.Forms.Label();
|
||||
this.txtSearch = new System.Windows.Forms.TextBox();
|
||||
this.lblSearch = new System.Windows.Forms.Label();
|
||||
this.pnlEdit = new System.Windows.Forms.Panel();
|
||||
this.grpEditInfo = new System.Windows.Forms.GroupBox();
|
||||
this.txtRemarks = new System.Windows.Forms.TextBox();
|
||||
this.lblRemarks = new System.Windows.Forms.Label();
|
||||
this.chkEnabled = new System.Windows.Forms.CheckBox();
|
||||
this.cmbLevel = new System.Windows.Forms.ComboBox();
|
||||
this.lblLevel = new System.Windows.Forms.Label();
|
||||
this.txtAlarmContent = new System.Windows.Forms.TextBox();
|
||||
this.lblAlarmContent = new System.Windows.Forms.Label();
|
||||
this.numAlarmCode = new System.Windows.Forms.NumericUpDown();
|
||||
this.lblAlarmCode = new System.Windows.Forms.Label();
|
||||
this.txtAlarmId = new System.Windows.Forms.TextBox();
|
||||
this.lblAlarmId = new System.Windows.Forms.Label();
|
||||
this.pnlEditButtons = new System.Windows.Forms.Panel();
|
||||
this.btnCancel = new System.Windows.Forms.Button();
|
||||
this.btnDelete = new System.Windows.Forms.Button();
|
||||
this.btnSave = new System.Windows.Forms.Button();
|
||||
this.colAlarmId = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.colAlarmCode = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.colAlarmContent = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.colLevel = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.colEnabled = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.colRemarks = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
|
||||
this.splitContainer.Panel1.SuspendLayout();
|
||||
this.splitContainer.Panel2.SuspendLayout();
|
||||
this.splitContainer.SuspendLayout();
|
||||
this.pnlList.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.dgvAlarmConfigs)).BeginInit();
|
||||
this.pnlListButtons.SuspendLayout();
|
||||
this.pnlSearch.SuspendLayout();
|
||||
this.pnlEdit.SuspendLayout();
|
||||
this.grpEditInfo.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numAlarmCode)).BeginInit();
|
||||
this.pnlEditButtons.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// splitContainer
|
||||
//
|
||||
this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.splitContainer.Location = new System.Drawing.Point(0, 0);
|
||||
this.splitContainer.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.splitContainer.Name = "splitContainer";
|
||||
//
|
||||
// splitContainer.Panel1
|
||||
//
|
||||
this.splitContainer.Panel1.Controls.Add(this.pnlList);
|
||||
//
|
||||
// splitContainer.Panel2
|
||||
//
|
||||
this.splitContainer.Panel2.Controls.Add(this.pnlEdit);
|
||||
this.splitContainer.Size = new System.Drawing.Size(1400, 750);
|
||||
this.splitContainer.SplitterDistance = 900;
|
||||
this.splitContainer.SplitterWidth = 5;
|
||||
this.splitContainer.TabIndex = 0;
|
||||
//
|
||||
// pnlList
|
||||
//
|
||||
this.pnlList.Controls.Add(this.dgvAlarmConfigs);
|
||||
this.pnlList.Controls.Add(this.pnlListButtons);
|
||||
this.pnlList.Controls.Add(this.pnlSearch);
|
||||
this.pnlList.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pnlList.Location = new System.Drawing.Point(0, 0);
|
||||
this.pnlList.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.pnlList.Name = "pnlList";
|
||||
this.pnlList.Size = new System.Drawing.Size(900, 750);
|
||||
this.pnlList.TabIndex = 0;
|
||||
//
|
||||
// dgvAlarmConfigs
|
||||
//
|
||||
this.dgvAlarmConfigs.AllowUserToAddRows = false;
|
||||
this.dgvAlarmConfigs.AllowUserToDeleteRows = false;
|
||||
this.dgvAlarmConfigs.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
|
||||
this.dgvAlarmConfigs.BackgroundColor = System.Drawing.Color.White;
|
||||
this.dgvAlarmConfigs.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
this.dgvAlarmConfigs.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.SingleHorizontal;
|
||||
dataGridViewCellStyle3.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
|
||||
dataGridViewCellStyle3.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(81)))), ((int)(((byte)(181)))));
|
||||
dataGridViewCellStyle3.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
dataGridViewCellStyle3.ForeColor = System.Drawing.Color.White;
|
||||
dataGridViewCellStyle3.SelectionBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(81)))), ((int)(((byte)(181)))));
|
||||
dataGridViewCellStyle3.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
dataGridViewCellStyle3.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
|
||||
this.dgvAlarmConfigs.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle3;
|
||||
this.dgvAlarmConfigs.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
this.dgvAlarmConfigs.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
|
||||
this.colAlarmId,
|
||||
this.colAlarmCode,
|
||||
this.colAlarmContent,
|
||||
this.colLevel,
|
||||
this.colEnabled,
|
||||
this.colRemarks});
|
||||
dataGridViewCellStyle4.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
|
||||
dataGridViewCellStyle4.BackColor = System.Drawing.Color.White;
|
||||
dataGridViewCellStyle4.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
dataGridViewCellStyle4.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
||||
dataGridViewCellStyle4.SelectionBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(197)))), ((int)(((byte)(202)))), ((int)(((byte)(233)))));
|
||||
dataGridViewCellStyle4.SelectionForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(33)))), ((int)(((byte)(33)))), ((int)(((byte)(33)))));
|
||||
dataGridViewCellStyle4.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this.dgvAlarmConfigs.DefaultCellStyle = dataGridViewCellStyle4;
|
||||
this.dgvAlarmConfigs.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.dgvAlarmConfigs.EnableHeadersVisualStyles = false;
|
||||
this.dgvAlarmConfigs.GridColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
|
||||
this.dgvAlarmConfigs.Location = new System.Drawing.Point(0, 62);
|
||||
this.dgvAlarmConfigs.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.dgvAlarmConfigs.MultiSelect = false;
|
||||
this.dgvAlarmConfigs.Name = "dgvAlarmConfigs";
|
||||
this.dgvAlarmConfigs.ReadOnly = true;
|
||||
this.dgvAlarmConfigs.RowHeadersVisible = false;
|
||||
this.dgvAlarmConfigs.RowHeadersWidth = 30;
|
||||
this.dgvAlarmConfigs.RowTemplate.Height = 35;
|
||||
this.dgvAlarmConfigs.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
|
||||
this.dgvAlarmConfigs.Size = new System.Drawing.Size(900, 600);
|
||||
this.dgvAlarmConfigs.TabIndex = 2;
|
||||
this.dgvAlarmConfigs.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dgvAlarmConfigs_CellDoubleClick);
|
||||
//
|
||||
// pnlListButtons
|
||||
//
|
||||
this.pnlListButtons.Controls.Add(this.lblStatistics);
|
||||
this.pnlListButtons.Controls.Add(this.btnClose);
|
||||
this.pnlListButtons.Controls.Add(this.btnRefresh);
|
||||
this.pnlListButtons.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.pnlListButtons.Location = new System.Drawing.Point(0, 662);
|
||||
this.pnlListButtons.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.pnlListButtons.Name = "pnlListButtons";
|
||||
this.pnlListButtons.Padding = new System.Windows.Forms.Padding(13, 12, 13, 12);
|
||||
this.pnlListButtons.Size = new System.Drawing.Size(900, 88);
|
||||
this.pnlListButtons.TabIndex = 1;
|
||||
//
|
||||
// lblStatistics
|
||||
//
|
||||
this.lblStatistics.AutoSize = true;
|
||||
this.lblStatistics.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.lblStatistics.Location = new System.Drawing.Point(20, 31);
|
||||
this.lblStatistics.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.lblStatistics.Name = "lblStatistics";
|
||||
this.lblStatistics.Size = new System.Drawing.Size(204, 24);
|
||||
this.lblStatistics.TabIndex = 2;
|
||||
this.lblStatistics.Text = "总数: 0 | 启用: 0 | 禁用: 0";
|
||||
//
|
||||
// btnClose
|
||||
//
|
||||
this.btnClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btnClose.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.btnClose.Location = new System.Drawing.Point(753, 19);
|
||||
this.btnClose.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.btnClose.Name = "btnClose";
|
||||
this.btnClose.Size = new System.Drawing.Size(120, 50);
|
||||
this.btnClose.TabIndex = 1;
|
||||
this.btnClose.Text = "关闭";
|
||||
this.btnClose.UseVisualStyleBackColor = true;
|
||||
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
|
||||
//
|
||||
// btnRefresh
|
||||
//
|
||||
this.btnRefresh.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btnRefresh.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.btnRefresh.Location = new System.Drawing.Point(620, 19);
|
||||
this.btnRefresh.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.btnRefresh.Name = "btnRefresh";
|
||||
this.btnRefresh.Size = new System.Drawing.Size(120, 50);
|
||||
this.btnRefresh.TabIndex = 0;
|
||||
this.btnRefresh.Text = "刷新";
|
||||
this.btnRefresh.UseVisualStyleBackColor = true;
|
||||
this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
|
||||
//
|
||||
// pnlSearch
|
||||
//
|
||||
this.pnlSearch.Controls.Add(this.cmbLevelFilter);
|
||||
this.pnlSearch.Controls.Add(this.lblLevelFilter);
|
||||
this.pnlSearch.Controls.Add(this.txtSearch);
|
||||
this.pnlSearch.Controls.Add(this.lblSearch);
|
||||
this.pnlSearch.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.pnlSearch.Location = new System.Drawing.Point(0, 0);
|
||||
this.pnlSearch.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.pnlSearch.Name = "pnlSearch";
|
||||
this.pnlSearch.Padding = new System.Windows.Forms.Padding(13, 12, 13, 12);
|
||||
this.pnlSearch.Size = new System.Drawing.Size(900, 62);
|
||||
this.pnlSearch.TabIndex = 0;
|
||||
//
|
||||
// cmbLevelFilter
|
||||
//
|
||||
this.cmbLevelFilter.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.cmbLevelFilter.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.cmbLevelFilter.FormattingEnabled = true;
|
||||
this.cmbLevelFilter.Location = new System.Drawing.Point(550, 16);
|
||||
this.cmbLevelFilter.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.cmbLevelFilter.Name = "cmbLevelFilter";
|
||||
this.cmbLevelFilter.Size = new System.Drawing.Size(150, 31);
|
||||
this.cmbLevelFilter.TabIndex = 3;
|
||||
this.cmbLevelFilter.SelectedIndexChanged += new System.EventHandler(this.cmbLevelFilter_SelectedIndexChanged);
|
||||
//
|
||||
// lblLevelFilter
|
||||
//
|
||||
this.lblLevelFilter.AutoSize = true;
|
||||
this.lblLevelFilter.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.lblLevelFilter.Location = new System.Drawing.Point(463, 21);
|
||||
this.lblLevelFilter.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.lblLevelFilter.Name = "lblLevelFilter";
|
||||
this.lblLevelFilter.Size = new System.Drawing.Size(61, 23);
|
||||
this.lblLevelFilter.TabIndex = 2;
|
||||
this.lblLevelFilter.Text = "级别:";
|
||||
//
|
||||
// txtSearch
|
||||
//
|
||||
this.txtSearch.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.txtSearch.Location = new System.Drawing.Point(100, 16);
|
||||
this.txtSearch.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.txtSearch.Name = "txtSearch";
|
||||
this.txtSearch.Size = new System.Drawing.Size(300, 29);
|
||||
this.txtSearch.TabIndex = 1;
|
||||
this.txtSearch.TextChanged += new System.EventHandler(this.txtSearch_TextChanged);
|
||||
//
|
||||
// lblSearch
|
||||
//
|
||||
this.lblSearch.AutoSize = true;
|
||||
this.lblSearch.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.lblSearch.Location = new System.Drawing.Point(13, 21);
|
||||
this.lblSearch.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.lblSearch.Name = "lblSearch";
|
||||
this.lblSearch.Size = new System.Drawing.Size(61, 23);
|
||||
this.lblSearch.TabIndex = 0;
|
||||
this.lblSearch.Text = "搜索:";
|
||||
//
|
||||
// pnlEdit
|
||||
//
|
||||
this.pnlEdit.Controls.Add(this.grpEditInfo);
|
||||
this.pnlEdit.Controls.Add(this.pnlEditButtons);
|
||||
this.pnlEdit.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pnlEdit.Location = new System.Drawing.Point(0, 0);
|
||||
this.pnlEdit.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.pnlEdit.Name = "pnlEdit";
|
||||
this.pnlEdit.Size = new System.Drawing.Size(495, 750);
|
||||
this.pnlEdit.TabIndex = 0;
|
||||
//
|
||||
// grpEditInfo
|
||||
//
|
||||
this.grpEditInfo.Controls.Add(this.txtRemarks);
|
||||
this.grpEditInfo.Controls.Add(this.lblRemarks);
|
||||
this.grpEditInfo.Controls.Add(this.chkEnabled);
|
||||
this.grpEditInfo.Controls.Add(this.cmbLevel);
|
||||
this.grpEditInfo.Controls.Add(this.lblLevel);
|
||||
this.grpEditInfo.Controls.Add(this.txtAlarmContent);
|
||||
this.grpEditInfo.Controls.Add(this.lblAlarmContent);
|
||||
this.grpEditInfo.Controls.Add(this.numAlarmCode);
|
||||
this.grpEditInfo.Controls.Add(this.lblAlarmCode);
|
||||
this.grpEditInfo.Controls.Add(this.txtAlarmId);
|
||||
this.grpEditInfo.Controls.Add(this.lblAlarmId);
|
||||
this.grpEditInfo.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.grpEditInfo.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.grpEditInfo.Location = new System.Drawing.Point(0, 0);
|
||||
this.grpEditInfo.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.grpEditInfo.Name = "grpEditInfo";
|
||||
this.grpEditInfo.Padding = new System.Windows.Forms.Padding(20, 19, 20, 19);
|
||||
this.grpEditInfo.Size = new System.Drawing.Size(495, 625);
|
||||
this.grpEditInfo.TabIndex = 1;
|
||||
this.grpEditInfo.TabStop = false;
|
||||
this.grpEditInfo.Text = "报警配置信息";
|
||||
//
|
||||
// txtRemarks
|
||||
//
|
||||
this.txtRemarks.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.txtRemarks.Location = new System.Drawing.Point(130, 350);
|
||||
this.txtRemarks.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.txtRemarks.Multiline = true;
|
||||
this.txtRemarks.Name = "txtRemarks";
|
||||
this.txtRemarks.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||
this.txtRemarks.Size = new System.Drawing.Size(330, 80);
|
||||
this.txtRemarks.TabIndex = 10;
|
||||
//
|
||||
// lblRemarks
|
||||
//
|
||||
this.lblRemarks.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.lblRemarks.Location = new System.Drawing.Point(27, 350);
|
||||
this.lblRemarks.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.lblRemarks.Name = "lblRemarks";
|
||||
this.lblRemarks.Size = new System.Drawing.Size(100, 31);
|
||||
this.lblRemarks.TabIndex = 9;
|
||||
this.lblRemarks.Text = "备注:";
|
||||
this.lblRemarks.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||
//
|
||||
// chkEnabled
|
||||
//
|
||||
this.chkEnabled.AutoSize = true;
|
||||
this.chkEnabled.Checked = true;
|
||||
this.chkEnabled.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.chkEnabled.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.chkEnabled.Location = new System.Drawing.Point(130, 300);
|
||||
this.chkEnabled.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.chkEnabled.Name = "chkEnabled";
|
||||
this.chkEnabled.Size = new System.Drawing.Size(83, 27);
|
||||
this.chkEnabled.TabIndex = 8;
|
||||
this.chkEnabled.Text = "启用中";
|
||||
this.chkEnabled.UseVisualStyleBackColor = true;
|
||||
this.chkEnabled.Visible = false;
|
||||
//
|
||||
// cmbLevel
|
||||
//
|
||||
this.cmbLevel.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.cmbLevel.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.cmbLevel.FormattingEnabled = true;
|
||||
this.cmbLevel.Location = new System.Drawing.Point(130, 244);
|
||||
this.cmbLevel.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.cmbLevel.Name = "cmbLevel";
|
||||
this.cmbLevel.Size = new System.Drawing.Size(330, 31);
|
||||
this.cmbLevel.TabIndex = 7;
|
||||
//
|
||||
// lblLevel
|
||||
//
|
||||
this.lblLevel.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.lblLevel.Location = new System.Drawing.Point(27, 244);
|
||||
this.lblLevel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.lblLevel.Name = "lblLevel";
|
||||
this.lblLevel.Size = new System.Drawing.Size(100, 31);
|
||||
this.lblLevel.TabIndex = 6;
|
||||
this.lblLevel.Text = "报警级别:";
|
||||
this.lblLevel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// txtAlarmContent
|
||||
//
|
||||
this.txtAlarmContent.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.txtAlarmContent.Location = new System.Drawing.Point(130, 181);
|
||||
this.txtAlarmContent.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.txtAlarmContent.Multiline = true;
|
||||
this.txtAlarmContent.Name = "txtAlarmContent";
|
||||
this.txtAlarmContent.Size = new System.Drawing.Size(330, 50);
|
||||
this.txtAlarmContent.TabIndex = 5;
|
||||
//
|
||||
// lblAlarmContent
|
||||
//
|
||||
this.lblAlarmContent.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.lblAlarmContent.Location = new System.Drawing.Point(27, 181);
|
||||
this.lblAlarmContent.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.lblAlarmContent.Name = "lblAlarmContent";
|
||||
this.lblAlarmContent.Size = new System.Drawing.Size(100, 31);
|
||||
this.lblAlarmContent.TabIndex = 4;
|
||||
this.lblAlarmContent.Text = "报警内容:";
|
||||
this.lblAlarmContent.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// numAlarmCode
|
||||
//
|
||||
this.numAlarmCode.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.numAlarmCode.Location = new System.Drawing.Point(130, 119);
|
||||
this.numAlarmCode.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.numAlarmCode.Maximum = new decimal(new int[] {
|
||||
99999,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.numAlarmCode.Name = "numAlarmCode";
|
||||
this.numAlarmCode.Size = new System.Drawing.Size(330, 29);
|
||||
this.numAlarmCode.TabIndex = 3;
|
||||
//
|
||||
// lblAlarmCode
|
||||
//
|
||||
this.lblAlarmCode.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.lblAlarmCode.Location = new System.Drawing.Point(27, 119);
|
||||
this.lblAlarmCode.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.lblAlarmCode.Name = "lblAlarmCode";
|
||||
this.lblAlarmCode.Size = new System.Drawing.Size(100, 31);
|
||||
this.lblAlarmCode.TabIndex = 2;
|
||||
this.lblAlarmCode.Text = "报警编码:";
|
||||
this.lblAlarmCode.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// txtAlarmId
|
||||
//
|
||||
this.txtAlarmId.BackColor = System.Drawing.Color.LightGray;
|
||||
this.txtAlarmId.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.txtAlarmId.Location = new System.Drawing.Point(130, 56);
|
||||
this.txtAlarmId.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.txtAlarmId.Name = "txtAlarmId";
|
||||
this.txtAlarmId.ReadOnly = true;
|
||||
this.txtAlarmId.Size = new System.Drawing.Size(330, 27);
|
||||
this.txtAlarmId.TabIndex = 1;
|
||||
this.txtAlarmId.Visible = false;
|
||||
//
|
||||
// lblAlarmId
|
||||
//
|
||||
this.lblAlarmId.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.lblAlarmId.Location = new System.Drawing.Point(27, 56);
|
||||
this.lblAlarmId.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.lblAlarmId.Name = "lblAlarmId";
|
||||
this.lblAlarmId.Size = new System.Drawing.Size(100, 31);
|
||||
this.lblAlarmId.TabIndex = 0;
|
||||
this.lblAlarmId.Text = "编号:";
|
||||
this.lblAlarmId.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
this.lblAlarmId.Visible = false;
|
||||
//
|
||||
// pnlEditButtons
|
||||
//
|
||||
this.pnlEditButtons.Controls.Add(this.btnCancel);
|
||||
this.pnlEditButtons.Controls.Add(this.btnDelete);
|
||||
this.pnlEditButtons.Controls.Add(this.btnSave);
|
||||
this.pnlEditButtons.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.pnlEditButtons.Location = new System.Drawing.Point(0, 625);
|
||||
this.pnlEditButtons.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.pnlEditButtons.Name = "pnlEditButtons";
|
||||
this.pnlEditButtons.Padding = new System.Windows.Forms.Padding(13, 12, 13, 12);
|
||||
this.pnlEditButtons.Size = new System.Drawing.Size(495, 125);
|
||||
this.pnlEditButtons.TabIndex = 0;
|
||||
//
|
||||
// btnCancel
|
||||
//
|
||||
this.btnCancel.Font = new System.Drawing.Font("微软雅黑", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.btnCancel.Location = new System.Drawing.Point(333, 25);
|
||||
this.btnCancel.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.btnCancel.Name = "btnCancel";
|
||||
this.btnCancel.Size = new System.Drawing.Size(133, 62);
|
||||
this.btnCancel.TabIndex = 2;
|
||||
this.btnCancel.Text = "取消";
|
||||
this.btnCancel.UseVisualStyleBackColor = true;
|
||||
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
|
||||
//
|
||||
// btnDelete
|
||||
//
|
||||
this.btnDelete.BackColor = System.Drawing.Color.LightCoral;
|
||||
this.btnDelete.Font = new System.Drawing.Font("微软雅黑", 11F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.btnDelete.Location = new System.Drawing.Point(180, 25);
|
||||
this.btnDelete.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.btnDelete.Name = "btnDelete";
|
||||
this.btnDelete.Size = new System.Drawing.Size(133, 62);
|
||||
this.btnDelete.TabIndex = 1;
|
||||
this.btnDelete.Text = "删除";
|
||||
this.btnDelete.UseVisualStyleBackColor = false;
|
||||
this.btnDelete.Click += new System.EventHandler(this.btnDelete_Click);
|
||||
//
|
||||
// btnSave
|
||||
//
|
||||
this.btnSave.BackColor = System.Drawing.Color.LightBlue;
|
||||
this.btnSave.Font = new System.Drawing.Font("微软雅黑", 11F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.btnSave.Location = new System.Drawing.Point(27, 25);
|
||||
this.btnSave.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.btnSave.Name = "btnSave";
|
||||
this.btnSave.Size = new System.Drawing.Size(133, 62);
|
||||
this.btnSave.TabIndex = 0;
|
||||
this.btnSave.Text = "新增";
|
||||
this.btnSave.UseVisualStyleBackColor = false;
|
||||
this.btnSave.Click += new System.EventHandler(this.btnSave_Click);
|
||||
//
|
||||
// colAlarmId
|
||||
//
|
||||
this.colAlarmId.HeaderText = "编号";
|
||||
this.colAlarmId.MinimumWidth = 6;
|
||||
this.colAlarmId.Name = "colAlarmId";
|
||||
this.colAlarmId.ReadOnly = true;
|
||||
this.colAlarmId.Visible = false;
|
||||
//
|
||||
// colAlarmCode
|
||||
//
|
||||
this.colAlarmCode.HeaderText = "报警编码";
|
||||
this.colAlarmCode.MinimumWidth = 6;
|
||||
this.colAlarmCode.Name = "colAlarmCode";
|
||||
this.colAlarmCode.ReadOnly = true;
|
||||
//
|
||||
// colAlarmContent
|
||||
//
|
||||
this.colAlarmContent.HeaderText = "报警内容";
|
||||
this.colAlarmContent.MinimumWidth = 6;
|
||||
this.colAlarmContent.Name = "colAlarmContent";
|
||||
this.colAlarmContent.ReadOnly = true;
|
||||
//
|
||||
// colLevel
|
||||
//
|
||||
this.colLevel.HeaderText = "级别";
|
||||
this.colLevel.MinimumWidth = 6;
|
||||
this.colLevel.Name = "colLevel";
|
||||
this.colLevel.ReadOnly = true;
|
||||
//
|
||||
// colEnabled
|
||||
//
|
||||
this.colEnabled.HeaderText = "启用";
|
||||
this.colEnabled.MinimumWidth = 6;
|
||||
this.colEnabled.Name = "colEnabled";
|
||||
this.colEnabled.ReadOnly = true;
|
||||
//
|
||||
// colRemarks
|
||||
//
|
||||
this.colRemarks.HeaderText = "备注";
|
||||
this.colRemarks.MinimumWidth = 6;
|
||||
this.colRemarks.Name = "colRemarks";
|
||||
this.colRemarks.ReadOnly = true;
|
||||
//
|
||||
// AlarmConfigManagementForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(1400, 750);
|
||||
this.Controls.Add(this.splitContainer);
|
||||
this.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.MinimumSize = new System.Drawing.Size(1200, 600);
|
||||
this.Name = "AlarmConfigManagementForm";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "报警配置管理";
|
||||
this.splitContainer.Panel1.ResumeLayout(false);
|
||||
this.splitContainer.Panel2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
|
||||
this.splitContainer.ResumeLayout(false);
|
||||
this.pnlList.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.dgvAlarmConfigs)).EndInit();
|
||||
this.pnlListButtons.ResumeLayout(false);
|
||||
this.pnlListButtons.PerformLayout();
|
||||
this.pnlSearch.ResumeLayout(false);
|
||||
this.pnlSearch.PerformLayout();
|
||||
this.pnlEdit.ResumeLayout(false);
|
||||
this.grpEditInfo.ResumeLayout(false);
|
||||
this.grpEditInfo.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numAlarmCode)).EndInit();
|
||||
this.pnlEditButtons.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.SplitContainer splitContainer;
|
||||
private System.Windows.Forms.Panel pnlList;
|
||||
private System.Windows.Forms.DataGridView dgvAlarmConfigs;
|
||||
private System.Windows.Forms.Panel pnlListButtons;
|
||||
private System.Windows.Forms.Label lblStatistics;
|
||||
private System.Windows.Forms.Button btnClose;
|
||||
private System.Windows.Forms.Button btnRefresh;
|
||||
private System.Windows.Forms.Panel pnlSearch;
|
||||
private System.Windows.Forms.ComboBox cmbLevelFilter;
|
||||
private System.Windows.Forms.Label lblLevelFilter;
|
||||
private System.Windows.Forms.TextBox txtSearch;
|
||||
private System.Windows.Forms.Label lblSearch;
|
||||
private System.Windows.Forms.Panel pnlEdit;
|
||||
private System.Windows.Forms.GroupBox grpEditInfo;
|
||||
private System.Windows.Forms.TextBox txtRemarks;
|
||||
private System.Windows.Forms.Label lblRemarks;
|
||||
private System.Windows.Forms.CheckBox chkEnabled;
|
||||
private System.Windows.Forms.ComboBox cmbLevel;
|
||||
private System.Windows.Forms.Label lblLevel;
|
||||
private System.Windows.Forms.TextBox txtAlarmContent;
|
||||
private System.Windows.Forms.Label lblAlarmContent;
|
||||
private System.Windows.Forms.NumericUpDown numAlarmCode;
|
||||
private System.Windows.Forms.Label lblAlarmCode;
|
||||
private System.Windows.Forms.TextBox txtAlarmId;
|
||||
private System.Windows.Forms.Label lblAlarmId;
|
||||
private System.Windows.Forms.Panel pnlEditButtons;
|
||||
private System.Windows.Forms.Button btnCancel;
|
||||
private System.Windows.Forms.Button btnDelete;
|
||||
private System.Windows.Forms.Button btnSave;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn colAlarmId;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn colAlarmCode;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn colAlarmContent;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn colLevel;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn colEnabled;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn colRemarks;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,240 +1,313 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using CycleGUI;
|
||||
using StandardScene.Utils;
|
||||
|
||||
namespace StandardScene.Charge
|
||||
{
|
||||
/// <summary>
|
||||
/// 报警配置管理窗体
|
||||
/// 报警配置管理界面(CycleGUI 版,替代原 WinForms 窗体)。
|
||||
/// </summary>
|
||||
public partial class AlarmConfigManagementForm : Form
|
||||
public class AlarmConfigManagementForm
|
||||
{
|
||||
private readonly AlarmConfigDataService dataService;
|
||||
private AlarmConfig selectedAlarmConfig;
|
||||
private const string TableId = "alarm-config-list";
|
||||
|
||||
public AlarmConfigManagementForm()
|
||||
private static readonly string[] LevelNames = { "无", "低", "中", "高", "严重" };
|
||||
private static readonly string[] LevelFilterNames = { "全部", "无", "低", "中", "高", "严重" };
|
||||
|
||||
private static readonly Color CriticalRowColor = Color.FromArgb(255, 235, 238);
|
||||
private static readonly Color HighRowColor = Color.FromArgb(255, 243, 224);
|
||||
private static readonly Color MediumRowColor = Color.FromArgb(255, 249, 196);
|
||||
private static readonly Color LowRowColor = Color.FromArgb(232, 245, 233);
|
||||
private static readonly Color DisabledRowColor = Color.FromArgb(238, 238, 238);
|
||||
|
||||
private static readonly AlarmConfigDataService DataService = AlarmConfigDataService.Instance;
|
||||
|
||||
private static Panel _panel;
|
||||
private static Panel _dialog;
|
||||
private static List<AlarmConfig> _allAlarms = new List<AlarmConfig>();
|
||||
private static int _levelFilterIdx;
|
||||
private static string _status = "";
|
||||
|
||||
/// <summary>打开(或置前)报警配置管理面板。兼容原 <c>new AlarmConfigManagementForm().Show()</c> 调用方式。</summary>
|
||||
public void Show() => Open();
|
||||
|
||||
/// <summary>打开(或置前)报警配置管理面板。</summary>
|
||||
public static void Open()
|
||||
{
|
||||
try
|
||||
if (_panel != null)
|
||||
{
|
||||
InitializeComponent();
|
||||
dataService = AlarmConfigDataService.Instance;
|
||||
|
||||
// 订阅Load事件,确保所有控件都已初始化后再加载数据
|
||||
this.Load += AlarmConfigManagementForm_Load;
|
||||
try
|
||||
{
|
||||
_panel.BringToFront();
|
||||
return;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_panel = null;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
LoadAlarms();
|
||||
|
||||
var panel = GUI.DeclarePanel()
|
||||
.ShowTitle("报警配置管理")
|
||||
.SetDefaultDocking(Panel.Docking.None)
|
||||
.InitSize(1100, 680)
|
||||
.InitPos(false, 0, 0, 0.5f, 0.5f, 0.5f, 0.5f);
|
||||
_panel = panel;
|
||||
panel.IfTerminalQuit(() => _panel = null);
|
||||
|
||||
panel.Define(pb =>
|
||||
{
|
||||
MessageBox.Show($"初始化报警配置管理窗体失败: {ex.Message}\n\n详细信息:\n{ex.StackTrace}",
|
||||
"错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 窗体加载事件
|
||||
/// </summary>
|
||||
private void AlarmConfigManagementForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
InitializeForm();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化窗体
|
||||
/// </summary>
|
||||
private void InitializeForm()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 初始化报警级别下拉框
|
||||
if (cmbLevel != null)
|
||||
{
|
||||
cmbLevel.Items.Clear();
|
||||
cmbLevel.Items.Add("无");
|
||||
cmbLevel.Items.Add("低");
|
||||
cmbLevel.Items.Add("中");
|
||||
cmbLevel.Items.Add("高");
|
||||
cmbLevel.Items.Add("严重");
|
||||
cmbLevel.SelectedIndex = 2; // 默认选择"中"
|
||||
}
|
||||
|
||||
// 初始化级别筛选下拉框
|
||||
if (cmbLevelFilter != null)
|
||||
{
|
||||
cmbLevelFilter.Items.Clear();
|
||||
cmbLevelFilter.Items.Add("全部");
|
||||
cmbLevelFilter.Items.Add("无");
|
||||
cmbLevelFilter.Items.Add("低");
|
||||
cmbLevelFilter.Items.Add("中");
|
||||
cmbLevelFilter.Items.Add("高");
|
||||
cmbLevelFilter.Items.Add("严重");
|
||||
cmbLevelFilter.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
LoadAlarmConfigs();
|
||||
ClearEditFields();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"初始化窗体失败: {ex.Message}\n\n{ex.StackTrace}", "错误",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载报警配置列表
|
||||
/// </summary>
|
||||
private void LoadAlarmConfigs()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (dgvAlarmConfigs == null)
|
||||
{
|
||||
return; // 控件还未初始化,直接返回
|
||||
}
|
||||
|
||||
var alarmConfigs = dataService.GetAllAlarmConfigs();
|
||||
|
||||
if (alarmConfigs == null)
|
||||
{
|
||||
alarmConfigs = new System.Collections.Generic.List<AlarmConfig>();
|
||||
}
|
||||
|
||||
// 根据级别筛选
|
||||
if (cmbLevelFilter != null && cmbLevelFilter.SelectedIndex > 0)
|
||||
{
|
||||
var filterLevel = (AlarmLevel)(cmbLevelFilter.SelectedIndex - 1);
|
||||
alarmConfigs = alarmConfigs.Where(a => a.Level == filterLevel).ToList();
|
||||
}
|
||||
|
||||
// 根据搜索文本筛选
|
||||
if (txtSearch != null && !string.IsNullOrWhiteSpace(txtSearch.Text))
|
||||
{
|
||||
var searchText = txtSearch.Text.Trim().ToLower();
|
||||
alarmConfigs = alarmConfigs.Where(a =>
|
||||
a.AlarmId.ToLower().Contains(searchText) ||
|
||||
a.AlarmCode.ToString().Contains(searchText) ||
|
||||
a.AlarmContent.ToLower().Contains(searchText)
|
||||
).ToList();
|
||||
}
|
||||
|
||||
dgvAlarmConfigs.Rows.Clear();
|
||||
|
||||
foreach (var alarm in alarmConfigs)
|
||||
{
|
||||
var index = dgvAlarmConfigs.Rows.Add(
|
||||
alarm.AlarmId,
|
||||
alarm.AlarmCode,
|
||||
alarm.AlarmContent,
|
||||
GetLevelText(alarm.Level),
|
||||
alarm.Enabled ? "是" : "否",
|
||||
alarm.Remarks
|
||||
);
|
||||
|
||||
// 根据级别设置行颜色
|
||||
var row = dgvAlarmConfigs.Rows[index];
|
||||
switch (alarm.Level)
|
||||
{
|
||||
case AlarmLevel.Critical:
|
||||
row.DefaultCellStyle.BackColor = Color.FromArgb(255, 235, 238); // 浅红色
|
||||
row.DefaultCellStyle.ForeColor = Color.FromArgb(183, 28, 28);
|
||||
// 安全地创建粗体字体
|
||||
var baseFont = row.DefaultCellStyle.Font ?? dgvAlarmConfigs.DefaultCellStyle.Font ?? new Font("微软雅黑", 9F);
|
||||
row.DefaultCellStyle.Font = new Font(baseFont, FontStyle.Bold);
|
||||
break;
|
||||
case AlarmLevel.High:
|
||||
row.DefaultCellStyle.BackColor = Color.FromArgb(255, 243, 224); // 浅橙色
|
||||
row.DefaultCellStyle.ForeColor = Color.FromArgb(230, 81, 0);
|
||||
break;
|
||||
case AlarmLevel.Medium:
|
||||
row.DefaultCellStyle.BackColor = Color.FromArgb(255, 249, 196); // 浅黄色
|
||||
row.DefaultCellStyle.ForeColor = Color.FromArgb(245, 127, 23);
|
||||
break;
|
||||
case AlarmLevel.Low:
|
||||
row.DefaultCellStyle.BackColor = Color.FromArgb(232, 245, 233); // 浅绿色
|
||||
row.DefaultCellStyle.ForeColor = Color.FromArgb(46, 125, 50);
|
||||
break;
|
||||
}
|
||||
|
||||
// 如果未启用,显示为灰色
|
||||
if (!alarm.Enabled)
|
||||
{
|
||||
row.DefaultCellStyle.BackColor = Color.FromArgb(238, 238, 238);
|
||||
row.DefaultCellStyle.ForeColor = Color.FromArgb(158, 158, 158);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateStatistics();
|
||||
UpdateTitleWithFilter(alarmConfigs.Count);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"加载数据失败: {ex.Message}", "错误",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新统计信息
|
||||
/// </summary>
|
||||
private void UpdateStatistics()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (lblStatistics == null)
|
||||
if (pb.Closing())
|
||||
{
|
||||
panel.Exit();
|
||||
_panel = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var alarmConfigs = dataService.GetAllAlarmConfigs();
|
||||
if (alarmConfigs == null)
|
||||
if (pb.Button("新增", distinct: "alarm-add"))
|
||||
OpenEditDialog(null);
|
||||
pb.SameLine(12);
|
||||
if (pb.Button("刷新", distinct: "alarm-refresh"))
|
||||
{
|
||||
alarmConfigs = new System.Collections.Generic.List<AlarmConfig>();
|
||||
DataService.Reload();
|
||||
LoadAlarms();
|
||||
_status = "数据已刷新";
|
||||
}
|
||||
pb.SameLine(12);
|
||||
if (pb.Button("关闭", distinct: "alarm-close"))
|
||||
{
|
||||
panel.Exit();
|
||||
_panel = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var total = alarmConfigs.Count;
|
||||
var enabled = alarmConfigs.Count(a => a.Enabled);
|
||||
var disabled = total - enabled;
|
||||
var critical = alarmConfigs.Count(a => a.Level == AlarmLevel.Critical);
|
||||
var high = alarmConfigs.Count(a => a.Level == AlarmLevel.High);
|
||||
pb.Separator();
|
||||
pb.DropdownBox("级别筛选", LevelFilterNames, ref _levelFilterIdx);
|
||||
|
||||
lblStatistics.Text = $"总数: {total} | 启用: {enabled} | 禁用: {disabled} | 严重: {critical} | 高级: {high}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"更新统计信息失败: {ex.Message}");
|
||||
}
|
||||
var filtered = GetFilteredAlarms();
|
||||
var totalCount = _allAlarms.Count;
|
||||
if (_levelFilterIdx > 0)
|
||||
pb.Label($"显示: {filtered.Count}/{totalCount} ({LevelFilterNames[_levelFilterIdx]})");
|
||||
else
|
||||
pb.Label($"总数: {totalCount} | {GetStatisticsText()}");
|
||||
|
||||
pb.Table(TableId,
|
||||
new[] { "报警编码", "报警内容", "级别", "启用", "备注", "操作" },
|
||||
filtered.Count, (row, i) =>
|
||||
{
|
||||
var alarm = filtered[i];
|
||||
if (!alarm.Enabled)
|
||||
row.SetColor(DisabledRowColor);
|
||||
else if (alarm.Level == AlarmLevel.Critical)
|
||||
row.SetColor(CriticalRowColor);
|
||||
else if (alarm.Level == AlarmLevel.High)
|
||||
row.SetColor(HighRowColor);
|
||||
else if (alarm.Level == AlarmLevel.Medium)
|
||||
row.SetColor(MediumRowColor);
|
||||
else if (alarm.Level == AlarmLevel.Low)
|
||||
row.SetColor(LowRowColor);
|
||||
|
||||
row.Label($"{alarm.AlarmCode}");
|
||||
row.Label(alarm.AlarmContent ?? "");
|
||||
row.Label(GetLevelText(alarm.Level));
|
||||
row.Label(alarm.Enabled ? "是" : "否");
|
||||
row.Label(alarm.Remarks ?? "");
|
||||
|
||||
if (row.ButtonGroup(new[] { "编辑" }, new[] { "编辑该报警配置" }) == 0)
|
||||
OpenEditDialog(alarm);
|
||||
}, height: 16, enableSearch: true);
|
||||
|
||||
if (!string.IsNullOrEmpty(_status))
|
||||
{
|
||||
pb.Separator();
|
||||
pb.Label(_status);
|
||||
}
|
||||
|
||||
pb.Panel.Repaint(repaintTimeMs: 500);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新标题显示筛选信息
|
||||
/// </summary>
|
||||
private void UpdateTitleWithFilter(int displayCount)
|
||||
private static void OpenEditDialog(AlarmConfig existing)
|
||||
{
|
||||
if (_dialog != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_dialog.BringToFront();
|
||||
return;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_dialog = null;
|
||||
}
|
||||
}
|
||||
|
||||
bool isAdd = existing == null;
|
||||
var draft = isAdd ? new AlarmConfig() : existing;
|
||||
|
||||
int levelIdx = (int)draft.Level;
|
||||
if (levelIdx < 0 || levelIdx >= LevelNames.Length)
|
||||
levelIdx = 2;
|
||||
|
||||
string codeText = draft.AlarmCode.ToString();
|
||||
string contentText = draft.AlarmContent ?? "";
|
||||
string remarksText = draft.Remarks ?? "";
|
||||
bool enabled = draft.Enabled;
|
||||
string err = "";
|
||||
|
||||
var dlg = GUI.DeclarePanel()
|
||||
.ShowTitle(isAdd ? "新增报警配置" : $"编辑报警配置 [{draft.AlarmCode}]")
|
||||
.SetDefaultDocking(Panel.Docking.None)
|
||||
.InitSize(460, 420)
|
||||
.InitPos(false, 0, 0, 0.5f, 0.5f, 0.5f, 0.5f);
|
||||
_dialog = dlg;
|
||||
dlg.IfTerminalQuit(() => _dialog = null);
|
||||
|
||||
dlg.Define(pb =>
|
||||
{
|
||||
if (pb.Closing())
|
||||
{
|
||||
dlg.Exit();
|
||||
_dialog = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAdd)
|
||||
pb.Label("编号: (新增时自动生成)");
|
||||
else
|
||||
pb.Label($"编号: {draft.AlarmId}");
|
||||
|
||||
var (code, _) = pb.TextInput("1. 报警编码 (0~99999)", codeText, alwaysReturnString: true);
|
||||
codeText = code;
|
||||
var (content, _) = pb.TextInput("2. 报警内容", contentText, alwaysReturnString: true);
|
||||
contentText = content;
|
||||
pb.DropdownBox("3. 报警级别", LevelNames, ref levelIdx);
|
||||
pb.CheckBox("4. 启用", ref enabled);
|
||||
var (remarks, _) = pb.TextInput("5. 备注", remarksText, alwaysReturnString: true);
|
||||
remarksText = remarks;
|
||||
|
||||
if (!string.IsNullOrEmpty(err))
|
||||
{
|
||||
pb.Separator();
|
||||
pb.Label(err);
|
||||
}
|
||||
|
||||
pb.Separator();
|
||||
if (pb.Button(isAdd ? "新增" : "保存", distinct: "alarm-edit-save"))
|
||||
{
|
||||
if (!int.TryParse(codeText?.Trim(), out var alarmCode) || alarmCode < 0 || alarmCode > 99999)
|
||||
{
|
||||
err = "报警编码需为 0~99999 的整数";
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(contentText))
|
||||
{
|
||||
err = "报警内容不能为空";
|
||||
return;
|
||||
}
|
||||
|
||||
draft.AlarmCode = alarmCode;
|
||||
draft.AlarmContent = contentText.Trim();
|
||||
draft.Level = (AlarmLevel)levelIdx;
|
||||
draft.Enabled = enabled;
|
||||
draft.Remarks = remarksText?.Trim() ?? "";
|
||||
|
||||
bool success;
|
||||
string errorMessage;
|
||||
if (isAdd)
|
||||
success = DataService.AddAlarmConfig(draft, out errorMessage);
|
||||
else
|
||||
success = DataService.UpdateAlarmConfig(draft, out errorMessage);
|
||||
|
||||
if (success)
|
||||
{
|
||||
CycleUiHelper.Alert("成功", "保存成功!");
|
||||
LoadAlarms();
|
||||
_status = isAdd ? "已新增报警配置" : $"已保存报警配置 [{draft.AlarmCode}]";
|
||||
dlg.Exit();
|
||||
_dialog = null;
|
||||
_panel?.Repaint();
|
||||
}
|
||||
else
|
||||
{
|
||||
err = $"保存失败: {errorMessage}";
|
||||
}
|
||||
}
|
||||
|
||||
if (!isAdd)
|
||||
{
|
||||
pb.SameLine(8);
|
||||
if (pb.Button("删除", distinct: "alarm-edit-delete"))
|
||||
{
|
||||
var toDelete = draft;
|
||||
CycleUiHelper.ConfirmThen(
|
||||
$"确定要删除报警配置 [{toDelete.AlarmCode}] {toDelete.AlarmContent} 吗?",
|
||||
() =>
|
||||
{
|
||||
if (DataService.DeleteAlarmConfig(toDelete.AlarmId, out string errorMessage))
|
||||
{
|
||||
CycleUiHelper.Alert("成功", "删除成功!");
|
||||
LoadAlarms();
|
||||
_status = $"已删除报警配置 [{toDelete.AlarmCode}]";
|
||||
dlg.Exit();
|
||||
_dialog = null;
|
||||
_panel?.Repaint();
|
||||
}
|
||||
else
|
||||
{
|
||||
CycleUiHelper.Alert("错误", $"删除失败: {errorMessage}");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pb.SameLine(8);
|
||||
if (pb.Button("取消", distinct: "alarm-edit-cancel"))
|
||||
{
|
||||
dlg.Exit();
|
||||
_dialog = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void LoadAlarms()
|
||||
{
|
||||
try
|
||||
{
|
||||
var allConfigs = dataService.GetAllAlarmConfigs();
|
||||
var totalCount = allConfigs != null ? allConfigs.Count : 0;
|
||||
|
||||
if (cmbLevelFilter != null && cmbLevelFilter.SelectedIndex > 0)
|
||||
{
|
||||
this.Text = $"报警配置管理 - 显示: {displayCount}/{totalCount} ({cmbLevelFilter.Text})";
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Text = $"报警配置管理 - 总数: {totalCount}";
|
||||
}
|
||||
_allAlarms = DataService.GetAllAlarmConfigs() ?? new List<AlarmConfig>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"更新标题失败: {ex.Message}");
|
||||
this.Text = "报警配置管理";
|
||||
_allAlarms = new List<AlarmConfig>();
|
||||
CycleUiHelper.Alert("错误", $"加载数据失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取级别文本
|
||||
/// </summary>
|
||||
private string GetLevelText(AlarmLevel level)
|
||||
private static List<AlarmConfig> GetFilteredAlarms()
|
||||
{
|
||||
IEnumerable<AlarmConfig> query = _allAlarms;
|
||||
if (_levelFilterIdx > 0)
|
||||
query = query.Where(a => a.Level == (AlarmLevel)(_levelFilterIdx - 1));
|
||||
return query.ToList();
|
||||
}
|
||||
|
||||
private static string GetStatisticsText()
|
||||
{
|
||||
var total = _allAlarms.Count;
|
||||
var enabled = _allAlarms.Count(a => a.Enabled);
|
||||
var disabled = total - enabled;
|
||||
var critical = _allAlarms.Count(a => a.Level == AlarmLevel.Critical);
|
||||
var high = _allAlarms.Count(a => a.Level == AlarmLevel.High);
|
||||
return $"启用: {enabled} | 禁用: {disabled} | 严重: {critical} | 高级: {high}";
|
||||
}
|
||||
|
||||
private static string GetLevelText(AlarmLevel level)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
@@ -247,301 +320,5 @@ namespace StandardScene.Charge
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空编辑字段
|
||||
/// </summary>
|
||||
private void ClearEditFields()
|
||||
{
|
||||
try
|
||||
{
|
||||
selectedAlarmConfig = null;
|
||||
|
||||
if (txtAlarmId != null)
|
||||
{
|
||||
txtAlarmId.Text = "";
|
||||
txtAlarmId.Enabled = false; // 新增时编号自动生成
|
||||
}
|
||||
|
||||
if (numAlarmCode != null)
|
||||
{
|
||||
numAlarmCode.Value = 0;
|
||||
numAlarmCode.Enabled = true;
|
||||
numAlarmCode.ReadOnly = false;
|
||||
}
|
||||
|
||||
if (txtAlarmContent != null)
|
||||
{
|
||||
txtAlarmContent.Text = "";
|
||||
txtAlarmContent.Enabled = true;
|
||||
txtAlarmContent.ReadOnly = false;
|
||||
}
|
||||
|
||||
if (cmbLevel != null)
|
||||
{
|
||||
cmbLevel.SelectedIndex = 2; // 中
|
||||
cmbLevel.Enabled = true;
|
||||
}
|
||||
|
||||
if (chkEnabled != null)
|
||||
{
|
||||
chkEnabled.Checked = true;
|
||||
chkEnabled.Enabled = true;
|
||||
}
|
||||
|
||||
if (txtRemarks != null)
|
||||
{
|
||||
txtRemarks.Text = "";
|
||||
txtRemarks.Enabled = true;
|
||||
txtRemarks.ReadOnly = false;
|
||||
}
|
||||
|
||||
if (btnSave != null)
|
||||
{
|
||||
btnSave.Text = "新增";
|
||||
btnSave.Enabled = true;
|
||||
}
|
||||
|
||||
if (btnDelete != null)
|
||||
{
|
||||
btnDelete.Enabled = false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"清空编辑字段失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从字段创建报警配置
|
||||
/// </summary>
|
||||
private AlarmConfig CreateAlarmConfigFromFields()
|
||||
{
|
||||
var alarmConfig = selectedAlarmConfig ?? new AlarmConfig();
|
||||
|
||||
alarmConfig.AlarmCode = (int)numAlarmCode.Value;
|
||||
alarmConfig.AlarmContent = txtAlarmContent.Text.Trim();
|
||||
alarmConfig.Level = (AlarmLevel)cmbLevel.SelectedIndex;
|
||||
alarmConfig.Enabled = chkEnabled.Checked;
|
||||
alarmConfig.Remarks = txtRemarks.Text.Trim();
|
||||
|
||||
return alarmConfig;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载报警配置到编辑区
|
||||
/// </summary>
|
||||
private void LoadAlarmConfigToFields(AlarmConfig alarmConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
selectedAlarmConfig = alarmConfig;
|
||||
|
||||
// 填充数据
|
||||
if (txtAlarmId != null)
|
||||
{
|
||||
txtAlarmId.Text = alarmConfig.AlarmId;
|
||||
txtAlarmId.Enabled = false; // 编号不可修改
|
||||
}
|
||||
|
||||
if (numAlarmCode != null)
|
||||
{
|
||||
numAlarmCode.Value = alarmConfig.AlarmCode;
|
||||
numAlarmCode.Enabled = true;
|
||||
numAlarmCode.ReadOnly = false;
|
||||
}
|
||||
|
||||
if (txtAlarmContent != null)
|
||||
{
|
||||
txtAlarmContent.Text = alarmConfig.AlarmContent;
|
||||
txtAlarmContent.Enabled = true;
|
||||
txtAlarmContent.ReadOnly = false;
|
||||
}
|
||||
|
||||
if (cmbLevel != null)
|
||||
{
|
||||
cmbLevel.SelectedIndex = (int)alarmConfig.Level;
|
||||
cmbLevel.Enabled = true;
|
||||
}
|
||||
|
||||
if (chkEnabled != null)
|
||||
{
|
||||
chkEnabled.Checked = alarmConfig.Enabled;
|
||||
chkEnabled.Enabled = true;
|
||||
}
|
||||
|
||||
if (txtRemarks != null)
|
||||
{
|
||||
txtRemarks.Text = alarmConfig.Remarks ?? "";
|
||||
txtRemarks.Enabled = true;
|
||||
txtRemarks.ReadOnly = false;
|
||||
}
|
||||
|
||||
// 设置按钮状态
|
||||
if (btnSave != null)
|
||||
{
|
||||
btnSave.Text = "保存";
|
||||
btnSave.Enabled = true;
|
||||
}
|
||||
|
||||
if (btnDelete != null)
|
||||
{
|
||||
btnDelete.Enabled = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"加载数据到编辑区失败: {ex.Message}\n\n{ex.StackTrace}", "错误",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 事件处理 ====================
|
||||
|
||||
private void btnSave_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 验证报警编码
|
||||
if (numAlarmCode.Value < 0)
|
||||
{
|
||||
MessageBox.Show("报警编码不能为负数", "验证失败",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
numAlarmCode.Focus();
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证报警内容
|
||||
if (string.IsNullOrWhiteSpace(txtAlarmContent.Text))
|
||||
{
|
||||
MessageBox.Show("报警内容不能为空", "验证失败",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
txtAlarmContent.Focus();
|
||||
return;
|
||||
}
|
||||
|
||||
var alarmConfig = CreateAlarmConfigFromFields();
|
||||
string errorMessage;
|
||||
|
||||
bool success;
|
||||
if (selectedAlarmConfig == null)
|
||||
{
|
||||
// 新增
|
||||
success = dataService.AddAlarmConfig(alarmConfig, out errorMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 更新
|
||||
success = dataService.UpdateAlarmConfig(alarmConfig, out errorMessage);
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
MessageBox.Show("保存成功!", "提示",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
LoadAlarmConfigs();
|
||||
ClearEditFields();
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show($"保存失败: {errorMessage}", "错误",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"保存失败: {ex.Message}", "错误",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void btnDelete_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (selectedAlarmConfig == null)
|
||||
{
|
||||
MessageBox.Show("请先选择要删除的报警配置", "提示",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var result = MessageBox.Show(
|
||||
$"确定要删除报警配置 [{selectedAlarmConfig.AlarmCode}] {selectedAlarmConfig.AlarmContent} 吗?",
|
||||
"确认删除",
|
||||
MessageBoxButtons.YesNo,
|
||||
MessageBoxIcon.Question);
|
||||
|
||||
if (result == DialogResult.Yes)
|
||||
{
|
||||
if (dataService.DeleteAlarmConfig(selectedAlarmConfig.AlarmId, out string errorMessage))
|
||||
{
|
||||
MessageBox.Show("删除成功!", "提示",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
LoadAlarmConfigs();
|
||||
ClearEditFields();
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show($"删除失败: {errorMessage}", "错误",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void btnCancel_Click(object sender, EventArgs e)
|
||||
{
|
||||
ClearEditFields();
|
||||
}
|
||||
|
||||
private void btnRefresh_Click(object sender, EventArgs e)
|
||||
{
|
||||
dataService.Reload();
|
||||
LoadAlarmConfigs();
|
||||
}
|
||||
|
||||
private void btnClose_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void dgvAlarmConfigs_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e.RowIndex >= 0 && e.RowIndex < dgvAlarmConfigs.Rows.Count)
|
||||
{
|
||||
var row = dgvAlarmConfigs.Rows[e.RowIndex];
|
||||
if (row.Cells[0].Value != null)
|
||||
{
|
||||
var alarmId = row.Cells[1].Value.ToString();
|
||||
var alarmConfig = dataService.GetAlarmConfigAlarmCode(int.Parse(alarmId));
|
||||
if (alarmConfig != null)
|
||||
{
|
||||
LoadAlarmConfigToFields(alarmConfig);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show($"未找到报警配置: {alarmId}", "提示",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"加载报警配置失败: {ex.Message}", "错误",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void txtSearch_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
LoadAlarmConfigs();
|
||||
}
|
||||
|
||||
private void cmbLevelFilter_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
LoadAlarmConfigs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -1,9 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using CycleGUI;
|
||||
using SimpleCore;
|
||||
using SimpleCore.Library;
|
||||
using StandardScene.Utils;
|
||||
|
||||
namespace StandardScene.Charge
|
||||
{
|
||||
@@ -13,36 +14,11 @@ namespace StandardScene.Charge
|
||||
/// </summary>
|
||||
public static class ChargeStationHelper
|
||||
{
|
||||
private static ChargeStationManagementForm _managementForm;
|
||||
/// <summary>打开充电桩管理面板(单实例)。</summary>
|
||||
public static void OpenManagementWindow() => ChargeStationManagementForm.Open();
|
||||
|
||||
/// <summary>
|
||||
/// 打开充电桩管理窗口(单例模式)
|
||||
/// </summary>
|
||||
public static void OpenManagementWindow()
|
||||
{
|
||||
if (_managementForm == null || _managementForm.IsDisposed)
|
||||
{
|
||||
_managementForm = new ChargeStationManagementForm();
|
||||
_managementForm.FormClosed += (s, e) => _managementForm = null;
|
||||
_managementForm.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
_managementForm.BringToFront();
|
||||
_managementForm.Activate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打开充电桩管理窗口(对话框模式)
|
||||
/// </summary>
|
||||
public static DialogResult OpenManagementDialog()
|
||||
{
|
||||
using (var form = new ChargeStationManagementForm())
|
||||
{
|
||||
return form.ShowDialog();
|
||||
}
|
||||
}
|
||||
/// <summary>打开充电桩管理面板(兼容旧 API)。</summary>
|
||||
public static void OpenManagementDialog() => ChargeStationManagementForm.Open();
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定站点的充电桩
|
||||
@@ -297,65 +273,44 @@ namespace StandardScene.Charge
|
||||
return success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示充电桩选择对话框
|
||||
/// </summary>
|
||||
/// <param name="filterByStatus">按状态过滤(null表示显示全部)</param>
|
||||
/// <returns>选中的充电桩,取消则返回null</returns>
|
||||
public static ChargeStation ShowStationSelectionDialog(ChargeStationStatus? filterByStatus = null)
|
||||
/// <summary>显示充电桩选择面板(非阻塞;通过 <paramref name="onSelected"/> 回调返回结果)。</summary>
|
||||
public static void ShowStationSelectionDialog(ChargeStationStatus? filterByStatus, System.Action<ChargeStation> onSelected)
|
||||
{
|
||||
var dataService = ChargeStationDataService.Instance;
|
||||
var stations = dataService.GetAllStations();
|
||||
|
||||
var stations = ChargeStationDataService.Instance.GetAllStations();
|
||||
if (filterByStatus.HasValue)
|
||||
{
|
||||
stations = stations.Where(s => s.Status == filterByStatus.Value).ToList();
|
||||
}
|
||||
|
||||
if (stations.Count == 0)
|
||||
{
|
||||
MessageBox.Show("没有符合条件的充电桩", "提示",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
return null;
|
||||
CycleUiHelper.Alert("提示", "没有符合条件的充电桩");
|
||||
onSelected?.Invoke(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建简单的选择对话框
|
||||
using (var dialog = new Form())
|
||||
var labels = stations.Select(s =>
|
||||
$"[{s.StationId}] {s.Name} - {s.IpAddress}:{s.Port} - {GetStatusText(s.Status)}").ToArray();
|
||||
int sel = 0;
|
||||
var dlg = GUI.DeclarePanel()
|
||||
.ShowTitle("选择充电桩")
|
||||
.TopMost(true)
|
||||
.InitSize(520, 400)
|
||||
.InitPos(false, 0, 0, 0.5f, 0.5f, 0.5f, 0.5f);
|
||||
dlg.Define(pb =>
|
||||
{
|
||||
dialog.Text = "选择充电桩";
|
||||
dialog.Size = new System.Drawing.Size(500, 400);
|
||||
dialog.StartPosition = FormStartPosition.CenterParent;
|
||||
|
||||
var listBox = new ListBox
|
||||
if (pb.Closing()) { dlg.Exit(); onSelected?.Invoke(null); return; }
|
||||
sel = pb.ListBox("充电桩", labels, height: 12);
|
||||
if (pb.Button("确定", distinct: "cs-pick-ok"))
|
||||
{
|
||||
Dock = DockStyle.Fill,
|
||||
Font = new System.Drawing.Font("微软雅黑", 10F)
|
||||
};
|
||||
|
||||
foreach (var station in stations)
|
||||
{
|
||||
listBox.Items.Add($"[{station.StationId}] {station.Name} - {station.IpAddress}:{station.Port} - {GetStatusText(station.Status)}");
|
||||
dlg.Exit();
|
||||
onSelected?.Invoke(sel >= 0 && sel < stations.Count ? stations[sel] : null);
|
||||
}
|
||||
|
||||
var btnOK = new Button
|
||||
pb.SameLine(8);
|
||||
if (pb.Button("取消", distinct: "cs-pick-cancel"))
|
||||
{
|
||||
Text = "确定",
|
||||
DialogResult = DialogResult.OK,
|
||||
Dock = DockStyle.Bottom,
|
||||
Height = 40
|
||||
};
|
||||
|
||||
dialog.Controls.Add(listBox);
|
||||
dialog.Controls.Add(btnOK);
|
||||
dialog.AcceptButton = btnOK;
|
||||
|
||||
if (dialog.ShowDialog() == DialogResult.OK && listBox.SelectedIndex >= 0)
|
||||
{
|
||||
return stations[listBox.SelectedIndex];
|
||||
dlg.Exit();
|
||||
onSelected?.Invoke(null);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,120 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -1,572 +0,0 @@
|
||||
namespace StandardScene.Charge
|
||||
{
|
||||
partial class ChargeStrategyConfigForm
|
||||
{
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
// 创建所有控件实例
|
||||
this.pnlMain = new System.Windows.Forms.Panel();
|
||||
this.pnlBottom = new System.Windows.Forms.Panel();
|
||||
this.grpSocParams = new System.Windows.Forms.GroupBox();
|
||||
this.grpTimeParams = new System.Windows.Forms.GroupBox();
|
||||
this.grpTaskParams = new System.Windows.Forms.GroupBox();
|
||||
this.grpSwitchParams = new System.Windows.Forms.GroupBox();
|
||||
|
||||
// SOC 参数控件
|
||||
this.lblMustChargeSoc = new System.Windows.Forms.Label();
|
||||
this.numMustChargeSoc = new System.Windows.Forms.NumericUpDown();
|
||||
this.lblIdleChargeSoc = new System.Windows.Forms.Label();
|
||||
this.numIdleChargeSoc = new System.Windows.Forms.NumericUpDown();
|
||||
this.lblTaskAvailableSoc = new System.Windows.Forms.Label();
|
||||
this.numTaskAvailableSoc = new System.Windows.Forms.NumericUpDown();
|
||||
this.lblFullChargeSoc = new System.Windows.Forms.Label();
|
||||
this.numFullChargeSoc = new System.Windows.Forms.NumericUpDown();
|
||||
this.lblAllowInterruptSoc = new System.Windows.Forms.Label();
|
||||
this.numAllowInterruptSoc = new System.Windows.Forms.NumericUpDown();
|
||||
|
||||
// 时间参数控件
|
||||
this.lblIdleChargeSeconds = new System.Windows.Forms.Label();
|
||||
this.numIdleChargeSeconds = new System.Windows.Forms.NumericUpDown();
|
||||
this.lblIdleSeconds = new System.Windows.Forms.Label();
|
||||
this.numIdleSeconds = new System.Windows.Forms.NumericUpDown();
|
||||
this.lblMustChargeSeconds = new System.Windows.Forms.Label();
|
||||
this.numMustChargeSeconds = new System.Windows.Forms.NumericUpDown();
|
||||
this.lblTopUpMinutes = new System.Windows.Forms.Label();
|
||||
this.numTopUpMinutes = new System.Windows.Forms.NumericUpDown();
|
||||
|
||||
// 任务参数控件
|
||||
this.lblMinAllowFreeCarToChargeTaskCnt = new System.Windows.Forms.Label();
|
||||
this.numMinAllowFreeCarToChargeTaskCnt = new System.Windows.Forms.NumericUpDown();
|
||||
|
||||
// 开关参数控件
|
||||
this.chkAllowInterruptTask = new System.Windows.Forms.CheckBox();
|
||||
this.chkUseLowerSocForCharge = new System.Windows.Forms.CheckBox();
|
||||
this.chkEnableErrorChargeDetection = new System.Windows.Forms.CheckBox();
|
||||
this.chkUseChargeSiteFilter = new System.Windows.Forms.CheckBox();
|
||||
|
||||
// 底部控件
|
||||
this.lblStatus = new System.Windows.Forms.Label();
|
||||
this.btnSave = new System.Windows.Forms.Button();
|
||||
this.btnApply = new System.Windows.Forms.Button();
|
||||
this.btnRestoreDefaults = new System.Windows.Forms.Button();
|
||||
this.btnCancel = new System.Windows.Forms.Button();
|
||||
this.pnlMain.SuspendLayout();
|
||||
this.grpSwitchParams.SuspendLayout();
|
||||
this.grpTaskParams.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numMinAllowFreeCarToChargeTaskCnt)).BeginInit();
|
||||
this.grpTimeParams.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numTopUpMinutes)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numMustChargeSeconds)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numIdleSeconds)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numIdleChargeSeconds)).BeginInit();
|
||||
this.grpSocParams.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numAllowInterruptSoc)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numFullChargeSoc)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numTaskAvailableSoc)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numIdleChargeSoc)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numMustChargeSoc)).BeginInit();
|
||||
this.pnlBottom.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// pnlMain
|
||||
//
|
||||
this.pnlMain.AutoScroll = true;
|
||||
this.pnlMain.Controls.Add(this.grpSwitchParams);
|
||||
this.pnlMain.Controls.Add(this.grpTaskParams);
|
||||
this.pnlMain.Controls.Add(this.grpTimeParams);
|
||||
this.pnlMain.Controls.Add(this.grpSocParams);
|
||||
this.pnlMain.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pnlMain.Location = new System.Drawing.Point(0, 0);
|
||||
this.pnlMain.Name = "pnlMain";
|
||||
this.pnlMain.Padding = new System.Windows.Forms.Padding(10);
|
||||
this.pnlMain.Size = new System.Drawing.Size(784, 631);
|
||||
this.pnlMain.TabIndex = 0;
|
||||
//
|
||||
// grpSwitchParams
|
||||
//
|
||||
this.grpSwitchParams.Controls.Add(this.chkUseChargeSiteFilter);
|
||||
this.grpSwitchParams.Controls.Add(this.chkEnableErrorChargeDetection);
|
||||
this.grpSwitchParams.Controls.Add(this.chkUseLowerSocForCharge);
|
||||
this.grpSwitchParams.Controls.Add(this.chkAllowInterruptTask);
|
||||
this.grpSwitchParams.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.grpSwitchParams.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Bold);
|
||||
this.grpSwitchParams.Location = new System.Drawing.Point(10, 460);
|
||||
this.grpSwitchParams.Name = "grpSwitchParams";
|
||||
this.grpSwitchParams.Padding = new System.Windows.Forms.Padding(10);
|
||||
this.grpSwitchParams.Size = new System.Drawing.Size(764, 150);
|
||||
this.grpSwitchParams.TabIndex = 3;
|
||||
this.grpSwitchParams.TabStop = false;
|
||||
this.grpSwitchParams.Text = "开关参数";
|
||||
//
|
||||
// chkUseChargeSiteFilter
|
||||
//
|
||||
this.chkUseChargeSiteFilter.AutoSize = true;
|
||||
this.chkUseChargeSiteFilter.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.chkUseChargeSiteFilter.Location = new System.Drawing.Point(400, 80);
|
||||
this.chkUseChargeSiteFilter.Name = "chkUseChargeSiteFilter";
|
||||
this.chkUseChargeSiteFilter.Size = new System.Drawing.Size(147, 24);
|
||||
this.chkUseChargeSiteFilter.TabIndex = 3;
|
||||
this.chkUseChargeSiteFilter.Text = "使用充电站点筛选";
|
||||
this.chkUseChargeSiteFilter.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkEnableErrorChargeDetection
|
||||
//
|
||||
this.chkEnableErrorChargeDetection.AutoSize = true;
|
||||
this.chkEnableErrorChargeDetection.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.chkEnableErrorChargeDetection.Location = new System.Drawing.Point(30, 80);
|
||||
this.chkEnableErrorChargeDetection.Name = "chkEnableErrorChargeDetection";
|
||||
this.chkEnableErrorChargeDetection.Size = new System.Drawing.Size(147, 24);
|
||||
this.chkEnableErrorChargeDetection.TabIndex = 2;
|
||||
this.chkEnableErrorChargeDetection.Text = "启用充电错误检测";
|
||||
this.chkEnableErrorChargeDetection.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkUseLowerSocForCharge
|
||||
//
|
||||
this.chkUseLowerSocForCharge.AutoSize = true;
|
||||
this.chkUseLowerSocForCharge.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.chkUseLowerSocForCharge.Location = new System.Drawing.Point(400, 40);
|
||||
this.chkUseLowerSocForCharge.Name = "chkUseLowerSocForCharge";
|
||||
this.chkUseLowerSocForCharge.Size = new System.Drawing.Size(195, 24);
|
||||
this.chkUseLowerSocForCharge.TabIndex = 1;
|
||||
this.chkUseLowerSocForCharge.Text = "优先使用低电量车辆充电";
|
||||
this.chkUseLowerSocForCharge.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkAllowInterruptTask
|
||||
//
|
||||
this.chkAllowInterruptTask.AutoSize = true;
|
||||
this.chkAllowInterruptTask.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.chkAllowInterruptTask.Location = new System.Drawing.Point(30, 40);
|
||||
this.chkAllowInterruptTask.Name = "chkAllowInterruptTask";
|
||||
this.chkAllowInterruptTask.Size = new System.Drawing.Size(147, 24);
|
||||
this.chkAllowInterruptTask.TabIndex = 0;
|
||||
this.chkAllowInterruptTask.Text = "允许中断充电任务";
|
||||
this.chkAllowInterruptTask.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// grpTaskParams
|
||||
//
|
||||
this.grpTaskParams.Controls.Add(this.numMinAllowFreeCarToChargeTaskCnt);
|
||||
this.grpTaskParams.Controls.Add(this.lblMinAllowFreeCarToChargeTaskCnt);
|
||||
this.grpTaskParams.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.grpTaskParams.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Bold);
|
||||
this.grpTaskParams.Location = new System.Drawing.Point(10, 370);
|
||||
this.grpTaskParams.Name = "grpTaskParams";
|
||||
this.grpTaskParams.Padding = new System.Windows.Forms.Padding(10);
|
||||
this.grpTaskParams.Size = new System.Drawing.Size(764, 90);
|
||||
this.grpTaskParams.TabIndex = 2;
|
||||
this.grpTaskParams.TabStop = false;
|
||||
this.grpTaskParams.Text = "任务参数";
|
||||
//
|
||||
// numMinAllowFreeCarToChargeTaskCnt
|
||||
//
|
||||
this.numMinAllowFreeCarToChargeTaskCnt.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.numMinAllowFreeCarToChargeTaskCnt.Location = new System.Drawing.Point(250, 40);
|
||||
this.numMinAllowFreeCarToChargeTaskCnt.Maximum = new decimal(new int[] {
|
||||
100,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.numMinAllowFreeCarToChargeTaskCnt.Name = "numMinAllowFreeCarToChargeTaskCnt";
|
||||
this.numMinAllowFreeCarToChargeTaskCnt.Size = new System.Drawing.Size(120, 27);
|
||||
this.numMinAllowFreeCarToChargeTaskCnt.TabIndex = 1;
|
||||
//
|
||||
// lblMinAllowFreeCarToChargeTaskCnt
|
||||
//
|
||||
this.lblMinAllowFreeCarToChargeTaskCnt.AutoSize = true;
|
||||
this.lblMinAllowFreeCarToChargeTaskCnt.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.lblMinAllowFreeCarToChargeTaskCnt.Location = new System.Drawing.Point(30, 42);
|
||||
this.lblMinAllowFreeCarToChargeTaskCnt.Name = "lblMinAllowFreeCarToChargeTaskCnt";
|
||||
this.lblMinAllowFreeCarToChargeTaskCnt.Size = new System.Drawing.Size(207, 20);
|
||||
this.lblMinAllowFreeCarToChargeTaskCnt.TabIndex = 0;
|
||||
this.lblMinAllowFreeCarToChargeTaskCnt.Text = "允许空闲车充电的最小任务数:";
|
||||
//
|
||||
// grpTimeParams
|
||||
//
|
||||
this.grpTimeParams.Controls.Add(this.numTopUpMinutes);
|
||||
this.grpTimeParams.Controls.Add(this.lblTopUpMinutes);
|
||||
this.grpTimeParams.Controls.Add(this.numMustChargeSeconds);
|
||||
this.grpTimeParams.Controls.Add(this.lblMustChargeSeconds);
|
||||
this.grpTimeParams.Controls.Add(this.numIdleSeconds);
|
||||
this.grpTimeParams.Controls.Add(this.lblIdleSeconds);
|
||||
this.grpTimeParams.Controls.Add(this.numIdleChargeSeconds);
|
||||
this.grpTimeParams.Controls.Add(this.lblIdleChargeSeconds);
|
||||
this.grpTimeParams.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.grpTimeParams.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Bold);
|
||||
this.grpTimeParams.Location = new System.Drawing.Point(10, 210);
|
||||
this.grpTimeParams.Name = "grpTimeParams";
|
||||
this.grpTimeParams.Padding = new System.Windows.Forms.Padding(10);
|
||||
this.grpTimeParams.Size = new System.Drawing.Size(764, 160);
|
||||
this.grpTimeParams.TabIndex = 1;
|
||||
this.grpTimeParams.TabStop = false;
|
||||
this.grpTimeParams.Text = "时间参数";
|
||||
//
|
||||
// numTopUpMinutes
|
||||
//
|
||||
this.numTopUpMinutes.DecimalPlaces = 1;
|
||||
this.numTopUpMinutes.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.numTopUpMinutes.Location = new System.Drawing.Point(580, 100);
|
||||
this.numTopUpMinutes.Maximum = new decimal(new int[] {
|
||||
1000,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.numTopUpMinutes.Name = "numTopUpMinutes";
|
||||
this.numTopUpMinutes.Size = new System.Drawing.Size(120, 27);
|
||||
this.numTopUpMinutes.TabIndex = 7;
|
||||
//
|
||||
// lblTopUpMinutes
|
||||
//
|
||||
this.lblTopUpMinutes.AutoSize = true;
|
||||
this.lblTopUpMinutes.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.lblTopUpMinutes.Location = new System.Drawing.Point(400, 102);
|
||||
this.lblTopUpMinutes.Name = "lblTopUpMinutes";
|
||||
this.lblTopUpMinutes.Size = new System.Drawing.Size(159, 20);
|
||||
this.lblTopUpMinutes.TabIndex = 6;
|
||||
this.lblTopUpMinutes.Text = "补电时间 (分钟,min):";
|
||||
//
|
||||
// numMustChargeSeconds
|
||||
//
|
||||
this.numMustChargeSeconds.DecimalPlaces = 1;
|
||||
this.numMustChargeSeconds.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.numMustChargeSeconds.Location = new System.Drawing.Point(250, 100);
|
||||
this.numMustChargeSeconds.Maximum = new decimal(new int[] {
|
||||
10000,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.numMustChargeSeconds.Name = "numMustChargeSeconds";
|
||||
this.numMustChargeSeconds.Size = new System.Drawing.Size(120, 27);
|
||||
this.numMustChargeSeconds.TabIndex = 5;
|
||||
//
|
||||
// lblMustChargeSeconds
|
||||
//
|
||||
this.lblMustChargeSeconds.AutoSize = true;
|
||||
this.lblMustChargeSeconds.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.lblMustChargeSeconds.Location = new System.Drawing.Point(30, 102);
|
||||
this.lblMustChargeSeconds.Name = "lblMustChargeSeconds";
|
||||
this.lblMustChargeSeconds.Size = new System.Drawing.Size(147, 20);
|
||||
this.lblMustChargeSeconds.TabIndex = 4;
|
||||
this.lblMustChargeSeconds.Text = "必充时间 (秒,sec):";
|
||||
//
|
||||
// numIdleSeconds
|
||||
//
|
||||
this.numIdleSeconds.DecimalPlaces = 1;
|
||||
this.numIdleSeconds.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.numIdleSeconds.Location = new System.Drawing.Point(580, 40);
|
||||
this.numIdleSeconds.Maximum = new decimal(new int[] {
|
||||
10000,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.numIdleSeconds.Name = "numIdleSeconds";
|
||||
this.numIdleSeconds.Size = new System.Drawing.Size(120, 27);
|
||||
this.numIdleSeconds.TabIndex = 3;
|
||||
//
|
||||
// lblIdleSeconds
|
||||
//
|
||||
this.lblIdleSeconds.AutoSize = true;
|
||||
this.lblIdleSeconds.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.lblIdleSeconds.Location = new System.Drawing.Point(400, 42);
|
||||
this.lblIdleSeconds.Name = "lblIdleSeconds";
|
||||
this.lblIdleSeconds.Size = new System.Drawing.Size(147, 20);
|
||||
this.lblIdleSeconds.TabIndex = 2;
|
||||
this.lblIdleSeconds.Text = "空闲时间 (秒,sec):";
|
||||
//
|
||||
// numIdleChargeSeconds
|
||||
//
|
||||
this.numIdleChargeSeconds.DecimalPlaces = 1;
|
||||
this.numIdleChargeSeconds.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.numIdleChargeSeconds.Location = new System.Drawing.Point(250, 40);
|
||||
this.numIdleChargeSeconds.Maximum = new decimal(new int[] {
|
||||
10000,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.numIdleChargeSeconds.Name = "numIdleChargeSeconds";
|
||||
this.numIdleChargeSeconds.Size = new System.Drawing.Size(120, 27);
|
||||
this.numIdleChargeSeconds.TabIndex = 1;
|
||||
//
|
||||
// lblIdleChargeSeconds
|
||||
//
|
||||
this.lblIdleChargeSeconds.AutoSize = true;
|
||||
this.lblIdleChargeSeconds.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.lblIdleChargeSeconds.Location = new System.Drawing.Point(30, 42);
|
||||
this.lblIdleChargeSeconds.Name = "lblIdleChargeSeconds";
|
||||
this.lblIdleChargeSeconds.Size = new System.Drawing.Size(171, 20);
|
||||
this.lblIdleChargeSeconds.TabIndex = 0;
|
||||
this.lblIdleChargeSeconds.Text = "空闲充电时间 (秒,sec):";
|
||||
//
|
||||
// grpSocParams
|
||||
//
|
||||
this.grpSocParams.Controls.Add(this.numAllowInterruptSoc);
|
||||
this.grpSocParams.Controls.Add(this.lblAllowInterruptSoc);
|
||||
this.grpSocParams.Controls.Add(this.numFullChargeSoc);
|
||||
this.grpSocParams.Controls.Add(this.lblFullChargeSoc);
|
||||
this.grpSocParams.Controls.Add(this.numTaskAvailableSoc);
|
||||
this.grpSocParams.Controls.Add(this.lblTaskAvailableSoc);
|
||||
this.grpSocParams.Controls.Add(this.numIdleChargeSoc);
|
||||
this.grpSocParams.Controls.Add(this.lblIdleChargeSoc);
|
||||
this.grpSocParams.Controls.Add(this.numMustChargeSoc);
|
||||
this.grpSocParams.Controls.Add(this.lblMustChargeSoc);
|
||||
this.grpSocParams.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.grpSocParams.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Bold);
|
||||
this.grpSocParams.Location = new System.Drawing.Point(10, 10);
|
||||
this.grpSocParams.Name = "grpSocParams";
|
||||
this.grpSocParams.Padding = new System.Windows.Forms.Padding(10);
|
||||
this.grpSocParams.Size = new System.Drawing.Size(764, 200);
|
||||
this.grpSocParams.TabIndex = 0;
|
||||
this.grpSocParams.TabStop = false;
|
||||
this.grpSocParams.Text = "SOC 参数 (电量百分比)";
|
||||
//
|
||||
// numAllowInterruptSoc
|
||||
//
|
||||
this.numAllowInterruptSoc.DecimalPlaces = 1;
|
||||
this.numAllowInterruptSoc.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.numAllowInterruptSoc.Location = new System.Drawing.Point(250, 150);
|
||||
this.numAllowInterruptSoc.Name = "numAllowInterruptSoc";
|
||||
this.numAllowInterruptSoc.Size = new System.Drawing.Size(120, 27);
|
||||
this.numAllowInterruptSoc.TabIndex = 9;
|
||||
//
|
||||
// lblAllowInterruptSoc
|
||||
//
|
||||
this.lblAllowInterruptSoc.AutoSize = true;
|
||||
this.lblAllowInterruptSoc.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.lblAllowInterruptSoc.Location = new System.Drawing.Point(30, 152);
|
||||
this.lblAllowInterruptSoc.Name = "lblAllowInterruptSoc";
|
||||
this.lblAllowInterruptSoc.Size = new System.Drawing.Size(135, 20);
|
||||
this.lblAllowInterruptSoc.TabIndex = 8;
|
||||
this.lblAllowInterruptSoc.Text = "允许中断电量 (%):";
|
||||
//
|
||||
// numFullChargeSoc
|
||||
//
|
||||
this.numFullChargeSoc.DecimalPlaces = 1;
|
||||
this.numFullChargeSoc.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.numFullChargeSoc.Location = new System.Drawing.Point(580, 95);
|
||||
this.numFullChargeSoc.Name = "numFullChargeSoc";
|
||||
this.numFullChargeSoc.Size = new System.Drawing.Size(120, 27);
|
||||
this.numFullChargeSoc.TabIndex = 7;
|
||||
//
|
||||
// lblFullChargeSoc
|
||||
//
|
||||
this.lblFullChargeSoc.AutoSize = true;
|
||||
this.lblFullChargeSoc.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.lblFullChargeSoc.Location = new System.Drawing.Point(400, 97);
|
||||
this.lblFullChargeSoc.Name = "lblFullChargeSoc";
|
||||
this.lblFullChargeSoc.Size = new System.Drawing.Size(99, 20);
|
||||
this.lblFullChargeSoc.TabIndex = 6;
|
||||
this.lblFullChargeSoc.Text = "满电电量 (%):";
|
||||
//
|
||||
// numTaskAvailableSoc
|
||||
//
|
||||
this.numTaskAvailableSoc.DecimalPlaces = 1;
|
||||
this.numTaskAvailableSoc.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.numTaskAvailableSoc.Location = new System.Drawing.Point(250, 95);
|
||||
this.numTaskAvailableSoc.Name = "numTaskAvailableSoc";
|
||||
this.numTaskAvailableSoc.Size = new System.Drawing.Size(120, 27);
|
||||
this.numTaskAvailableSoc.TabIndex = 5;
|
||||
//
|
||||
// lblTaskAvailableSoc
|
||||
//
|
||||
this.lblTaskAvailableSoc.AutoSize = true;
|
||||
this.lblTaskAvailableSoc.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.lblTaskAvailableSoc.Location = new System.Drawing.Point(30, 97);
|
||||
this.lblTaskAvailableSoc.Name = "lblTaskAvailableSoc";
|
||||
this.lblTaskAvailableSoc.Size = new System.Drawing.Size(135, 20);
|
||||
this.lblTaskAvailableSoc.TabIndex = 4;
|
||||
this.lblTaskAvailableSoc.Text = "任务可用电量 (%):";
|
||||
//
|
||||
// numIdleChargeSoc
|
||||
//
|
||||
this.numIdleChargeSoc.DecimalPlaces = 1;
|
||||
this.numIdleChargeSoc.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.numIdleChargeSoc.Location = new System.Drawing.Point(580, 40);
|
||||
this.numIdleChargeSoc.Name = "numIdleChargeSoc";
|
||||
this.numIdleChargeSoc.Size = new System.Drawing.Size(120, 27);
|
||||
this.numIdleChargeSoc.TabIndex = 3;
|
||||
//
|
||||
// lblIdleChargeSoc
|
||||
//
|
||||
this.lblIdleChargeSoc.AutoSize = true;
|
||||
this.lblIdleChargeSoc.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.lblIdleChargeSoc.Location = new System.Drawing.Point(400, 42);
|
||||
this.lblIdleChargeSoc.Name = "lblIdleChargeSoc";
|
||||
this.lblIdleChargeSoc.Size = new System.Drawing.Size(135, 20);
|
||||
this.lblIdleChargeSoc.TabIndex = 2;
|
||||
this.lblIdleChargeSoc.Text = "空闲充电电量 (%):";
|
||||
//
|
||||
// numMustChargeSoc
|
||||
//
|
||||
this.numMustChargeSoc.DecimalPlaces = 1;
|
||||
this.numMustChargeSoc.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.numMustChargeSoc.Location = new System.Drawing.Point(250, 40);
|
||||
this.numMustChargeSoc.Name = "numMustChargeSoc";
|
||||
this.numMustChargeSoc.Size = new System.Drawing.Size(120, 27);
|
||||
this.numMustChargeSoc.TabIndex = 1;
|
||||
//
|
||||
// lblMustChargeSoc
|
||||
//
|
||||
this.lblMustChargeSoc.AutoSize = true;
|
||||
this.lblMustChargeSoc.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.lblMustChargeSoc.Location = new System.Drawing.Point(30, 42);
|
||||
this.lblMustChargeSoc.Name = "lblMustChargeSoc";
|
||||
this.lblMustChargeSoc.Size = new System.Drawing.Size(99, 20);
|
||||
this.lblMustChargeSoc.TabIndex = 0;
|
||||
this.lblMustChargeSoc.Text = "必充电量 (%):";
|
||||
//
|
||||
// pnlBottom
|
||||
//
|
||||
this.pnlBottom.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(250)))), ((int)(((byte)(250)))), ((int)(((byte)(250)))));
|
||||
this.pnlBottom.Controls.Add(this.lblStatus);
|
||||
this.pnlBottom.Controls.Add(this.btnApply);
|
||||
this.pnlBottom.Controls.Add(this.btnRestoreDefaults);
|
||||
this.pnlBottom.Controls.Add(this.btnCancel);
|
||||
this.pnlBottom.Controls.Add(this.btnSave);
|
||||
this.pnlBottom.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.pnlBottom.Location = new System.Drawing.Point(0, 631);
|
||||
this.pnlBottom.Name = "pnlBottom";
|
||||
this.pnlBottom.Size = new System.Drawing.Size(784, 70);
|
||||
this.pnlBottom.TabIndex = 1;
|
||||
//
|
||||
// lblStatus
|
||||
//
|
||||
this.lblStatus.AutoSize = true;
|
||||
this.lblStatus.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.lblStatus.Location = new System.Drawing.Point(20, 25);
|
||||
this.lblStatus.Name = "lblStatus";
|
||||
this.lblStatus.Size = new System.Drawing.Size(54, 20);
|
||||
this.lblStatus.TabIndex = 4;
|
||||
this.lblStatus.Text = "就绪...";
|
||||
//
|
||||
// btnApply
|
||||
//
|
||||
this.btnApply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btnApply.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.btnApply.Location = new System.Drawing.Point(564, 18);
|
||||
this.btnApply.Name = "btnApply";
|
||||
this.btnApply.Size = new System.Drawing.Size(100, 35);
|
||||
this.btnApply.TabIndex = 3;
|
||||
this.btnApply.Text = "应用";
|
||||
this.btnApply.UseVisualStyleBackColor = true;
|
||||
this.btnApply.Click += new System.EventHandler(this.btnApply_Click);
|
||||
//
|
||||
// btnRestoreDefaults
|
||||
//
|
||||
this.btnRestoreDefaults.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btnRestoreDefaults.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.btnRestoreDefaults.Location = new System.Drawing.Point(344, 18);
|
||||
this.btnRestoreDefaults.Name = "btnRestoreDefaults";
|
||||
this.btnRestoreDefaults.Size = new System.Drawing.Size(100, 35);
|
||||
this.btnRestoreDefaults.TabIndex = 2;
|
||||
this.btnRestoreDefaults.Text = "恢复默认";
|
||||
this.btnRestoreDefaults.UseVisualStyleBackColor = true;
|
||||
this.btnRestoreDefaults.Click += new System.EventHandler(this.btnRestoreDefaults_Click);
|
||||
//
|
||||
// btnCancel
|
||||
//
|
||||
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btnCancel.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.btnCancel.Location = new System.Drawing.Point(674, 18);
|
||||
this.btnCancel.Name = "btnCancel";
|
||||
this.btnCancel.Size = new System.Drawing.Size(100, 35);
|
||||
this.btnCancel.TabIndex = 1;
|
||||
this.btnCancel.Text = "取消";
|
||||
this.btnCancel.UseVisualStyleBackColor = true;
|
||||
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
|
||||
//
|
||||
// btnSave
|
||||
//
|
||||
this.btnSave.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btnSave.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||
this.btnSave.Location = new System.Drawing.Point(454, 18);
|
||||
this.btnSave.Name = "btnSave";
|
||||
this.btnSave.Size = new System.Drawing.Size(100, 35);
|
||||
this.btnSave.TabIndex = 0;
|
||||
this.btnSave.Text = "保存";
|
||||
this.btnSave.UseVisualStyleBackColor = true;
|
||||
this.btnSave.Click += new System.EventHandler(this.btnSave_Click);
|
||||
//
|
||||
// ChargeStrategyConfigForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(784, 701);
|
||||
this.Controls.Add(this.pnlMain);
|
||||
this.Controls.Add(this.pnlBottom);
|
||||
this.Name = "ChargeStrategyConfigForm";
|
||||
this.Text = "充电策略配置";
|
||||
this.pnlMain.ResumeLayout(false);
|
||||
this.grpSwitchParams.ResumeLayout(false);
|
||||
this.grpSwitchParams.PerformLayout();
|
||||
this.grpTaskParams.ResumeLayout(false);
|
||||
this.grpTaskParams.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numMinAllowFreeCarToChargeTaskCnt)).EndInit();
|
||||
this.grpTimeParams.ResumeLayout(false);
|
||||
this.grpTimeParams.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numTopUpMinutes)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numMustChargeSeconds)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numIdleSeconds)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numIdleChargeSeconds)).EndInit();
|
||||
this.grpSocParams.ResumeLayout(false);
|
||||
this.grpSocParams.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numAllowInterruptSoc)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numFullChargeSoc)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numTaskAvailableSoc)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numIdleChargeSoc)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numMustChargeSoc)).EndInit();
|
||||
this.pnlBottom.ResumeLayout(false);
|
||||
this.pnlBottom.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Panel pnlMain;
|
||||
private System.Windows.Forms.GroupBox grpSocParams;
|
||||
private System.Windows.Forms.NumericUpDown numMustChargeSoc;
|
||||
private System.Windows.Forms.Label lblMustChargeSoc;
|
||||
private System.Windows.Forms.NumericUpDown numIdleChargeSoc;
|
||||
private System.Windows.Forms.Label lblIdleChargeSoc;
|
||||
private System.Windows.Forms.NumericUpDown numTaskAvailableSoc;
|
||||
private System.Windows.Forms.Label lblTaskAvailableSoc;
|
||||
private System.Windows.Forms.NumericUpDown numFullChargeSoc;
|
||||
private System.Windows.Forms.Label lblFullChargeSoc;
|
||||
private System.Windows.Forms.NumericUpDown numAllowInterruptSoc;
|
||||
private System.Windows.Forms.Label lblAllowInterruptSoc;
|
||||
private System.Windows.Forms.GroupBox grpTimeParams;
|
||||
private System.Windows.Forms.NumericUpDown numIdleChargeSeconds;
|
||||
private System.Windows.Forms.Label lblIdleChargeSeconds;
|
||||
private System.Windows.Forms.NumericUpDown numIdleSeconds;
|
||||
private System.Windows.Forms.Label lblIdleSeconds;
|
||||
private System.Windows.Forms.NumericUpDown numMustChargeSeconds;
|
||||
private System.Windows.Forms.Label lblMustChargeSeconds;
|
||||
private System.Windows.Forms.NumericUpDown numTopUpMinutes;
|
||||
private System.Windows.Forms.Label lblTopUpMinutes;
|
||||
private System.Windows.Forms.GroupBox grpTaskParams;
|
||||
private System.Windows.Forms.NumericUpDown numMinAllowFreeCarToChargeTaskCnt;
|
||||
private System.Windows.Forms.Label lblMinAllowFreeCarToChargeTaskCnt;
|
||||
private System.Windows.Forms.GroupBox grpSwitchParams;
|
||||
private System.Windows.Forms.CheckBox chkAllowInterruptTask;
|
||||
private System.Windows.Forms.CheckBox chkUseLowerSocForCharge;
|
||||
private System.Windows.Forms.CheckBox chkEnableErrorChargeDetection;
|
||||
private System.Windows.Forms.CheckBox chkUseChargeSiteFilter;
|
||||
private System.Windows.Forms.Panel pnlBottom;
|
||||
private System.Windows.Forms.Button btnSave;
|
||||
private System.Windows.Forms.Button btnCancel;
|
||||
private System.Windows.Forms.Button btnRestoreDefaults;
|
||||
private System.Windows.Forms.Button btnApply;
|
||||
private System.Windows.Forms.Label lblStatus;
|
||||
}
|
||||
}
|
||||
@@ -1,215 +1,259 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using CycleGUI;
|
||||
using StandardScene.Utils;
|
||||
|
||||
namespace StandardScene.Charge
|
||||
{
|
||||
/// <summary>
|
||||
/// 充电策略配置窗体
|
||||
/// 充电策略配置界面(CycleGUI 版,替代原 WinForms 窗体)。
|
||||
/// </summary>
|
||||
public partial class ChargeStrategyConfigForm : Form
|
||||
public class ChargeStrategyConfigForm
|
||||
{
|
||||
private ChargeStrategyConfig config;
|
||||
private ChargeStrategyConfigService configService;
|
||||
private static Panel _panel;
|
||||
private static readonly ChargeStrategyConfigService ConfigService = ChargeStrategyConfigService.Instance;
|
||||
|
||||
public ChargeStrategyConfigForm()
|
||||
private static ChargeStrategyConfig _config;
|
||||
private static string _status = "";
|
||||
|
||||
// SOC 参数
|
||||
private static float _mustChargeSoc;
|
||||
private static float _idleChargeSoc;
|
||||
private static float _taskAvailableSoc;
|
||||
private static float _fullChargeSoc;
|
||||
private static float _allowInterruptSoc;
|
||||
|
||||
// 时间参数
|
||||
private static float _idleChargeSeconds;
|
||||
private static float _idleSeconds;
|
||||
private static float _mustChargeSeconds;
|
||||
private static float _topUpMinutes;
|
||||
|
||||
// 任务参数
|
||||
private static int _minAllowFreeCarToChargeTaskCnt;
|
||||
|
||||
// 开关参数
|
||||
private static bool _allowInterruptTask;
|
||||
private static bool _useLowerSocForCharge;
|
||||
private static bool _enableErrorChargeDetection;
|
||||
private static bool _useChargeSiteFilter;
|
||||
|
||||
/// <summary>打开(或置前)充电策略配置面板。兼容原 <c>new ChargeStrategyConfigForm().Show()</c> 调用方式。</summary>
|
||||
public void Show() => Open();
|
||||
|
||||
/// <summary>打开(或置前)充电策略配置面板。</summary>
|
||||
public static void Open()
|
||||
{
|
||||
InitializeComponent();
|
||||
configService = ChargeStrategyConfigService.Instance;
|
||||
InitializeForm();
|
||||
}
|
||||
|
||||
private void InitializeForm()
|
||||
{
|
||||
this.Text = "充电策略配置";
|
||||
this.Size = new Size(800, 700);
|
||||
this.StartPosition = FormStartPosition.CenterScreen;
|
||||
this.MinimumSize = new Size(700, 600);
|
||||
this.FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
this.MaximizeBox = false;
|
||||
|
||||
// 加载配置
|
||||
LoadConfig();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载配置到界面
|
||||
/// </summary>
|
||||
private void LoadConfig(bool isDef = false)
|
||||
{
|
||||
try
|
||||
if (_panel != null)
|
||||
{
|
||||
if (!isDef)
|
||||
try
|
||||
{
|
||||
config = configService.LoadConfig();
|
||||
_panel.BringToFront();
|
||||
return;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_panel = null;
|
||||
}
|
||||
|
||||
|
||||
// SOC 相关参数
|
||||
numMustChargeSoc.Value = (decimal)config.MustChargeSoc;
|
||||
numIdleChargeSoc.Value = (decimal)config.IdleChargeSoc;
|
||||
numTaskAvailableSoc.Value = (decimal)config.TaskAvailableSoc;
|
||||
numFullChargeSoc.Value = (decimal)config.FullChargeSoc;
|
||||
numAllowInterruptSoc.Value = (decimal)config.AllowInterruptSoc;
|
||||
|
||||
// 时间相关参数
|
||||
numIdleChargeSeconds.Value = (decimal)config.IdleChargeSeconds;
|
||||
numIdleSeconds.Value = (decimal)config.IdleSeconds;
|
||||
numMustChargeSeconds.Value = (decimal)config.MustChargeSeconds;
|
||||
numTopUpMinutes.Value = (decimal)config.TopUpMinutes;
|
||||
|
||||
// 任务相关参数
|
||||
numMinAllowFreeCarToChargeTaskCnt.Value = config.MinAllowFreeCarToChargeTaskCnt;
|
||||
|
||||
// 开关参数
|
||||
chkAllowInterruptTask.Checked = config.AllowInterruptTask;
|
||||
chkUseLowerSocForCharge.Checked = config.UseLowerSocForCharge;
|
||||
chkEnableErrorChargeDetection.Checked = config.EnableErrorChargeDetection;
|
||||
chkUseChargeSiteFilter.Checked = config.UseChargeSiteFilter;
|
||||
|
||||
lblStatus.Text = "配置加载成功";
|
||||
lblStatus.ForeColor = Color.Green;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
if (!TryLoadConfig())
|
||||
return;
|
||||
|
||||
var panel = GUI.DeclarePanel()
|
||||
.ShowTitle("充电策略配置")
|
||||
.SetDefaultDocking(Panel.Docking.None)
|
||||
.InitSize(780, 680)
|
||||
.InitPos(false, 0, 0, 0.5f, 0.5f, 0.5f, 0.5f);
|
||||
_panel = panel;
|
||||
panel.IfTerminalQuit(() => _panel = null);
|
||||
|
||||
panel.Define(pb =>
|
||||
{
|
||||
MessageBox.Show($"加载配置失败: {ex.Message}", "错误",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
lblStatus.Text = "配置加载失败";
|
||||
lblStatus.ForeColor = Color.Red;
|
||||
}
|
||||
if (pb.Closing())
|
||||
{
|
||||
panel.Exit();
|
||||
_panel = null;
|
||||
return;
|
||||
}
|
||||
|
||||
pb.SeparatorText("SOC 参数 (电量百分比)");
|
||||
pb.DragFloat("1. 必充电量 (%)", ref _mustChargeSoc, step: 0.1f, min: 0, max: 100);
|
||||
pb.DragFloat("2. 空闲充电电量 (%)", ref _idleChargeSoc, step: 0.1f, min: 0, max: 100);
|
||||
pb.DragFloat("3. 任务可用电量 (%)", ref _taskAvailableSoc, step: 0.1f, min: 0, max: 100);
|
||||
pb.DragFloat("4. 满电电量 (%)", ref _fullChargeSoc, step: 0.1f, min: 0, max: 100);
|
||||
pb.DragFloat("5. 允许中断电量 (%)", ref _allowInterruptSoc, step: 0.1f, min: 0, max: 100);
|
||||
|
||||
pb.SeparatorText("时间参数");
|
||||
pb.DragFloat("6. 空闲充电时间 (秒)", ref _idleChargeSeconds, step: 0.1f, min: 0, max: 10000);
|
||||
pb.DragFloat("7. 空闲时间 (秒)", ref _idleSeconds, step: 0.1f, min: 0, max: 10000);
|
||||
pb.DragFloat("8. 必充时间 (秒)", ref _mustChargeSeconds, step: 0.1f, min: 0, max: 10000);
|
||||
pb.DragFloat("9. 补电时间 (分钟)", ref _topUpMinutes, step: 0.1f, min: 0, max: 1000);
|
||||
|
||||
pb.SeparatorText("任务参数");
|
||||
pb.SliderInt("10. 允许空闲车充电的最小任务数", ref _minAllowFreeCarToChargeTaskCnt, min: 0, max: 100);
|
||||
|
||||
pb.SeparatorText("开关参数");
|
||||
pb.CheckBox("11. 允许中断充电任务", ref _allowInterruptTask);
|
||||
pb.CheckBox("12. 优先使用低电量车辆充电", ref _useLowerSocForCharge);
|
||||
pb.CheckBox("13. 启用充电错误检测", ref _enableErrorChargeDetection);
|
||||
pb.CheckBox("14. 使用充电站点筛选", ref _useChargeSiteFilter);
|
||||
|
||||
pb.Separator();
|
||||
if (!string.IsNullOrEmpty(_status))
|
||||
pb.Label(_status);
|
||||
|
||||
pb.Separator();
|
||||
if (pb.Button("保存", distinct: "charge-strategy-save"))
|
||||
TrySave(closeAfterSave: false);
|
||||
pb.SameLine(8);
|
||||
if (pb.Button("应用", distinct: "charge-strategy-apply"))
|
||||
TrySave(closeAfterSave: false);
|
||||
pb.SameLine(8);
|
||||
if (pb.Button("恢复默认", distinct: "charge-strategy-restore"))
|
||||
RestoreDefaults();
|
||||
pb.SameLine(8);
|
||||
if (pb.Button("取消", distinct: "charge-strategy-cancel"))
|
||||
{
|
||||
panel.Exit();
|
||||
_panel = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从界面保存配置
|
||||
/// </summary>
|
||||
private void SaveConfig()
|
||||
private static bool TryLoadConfig()
|
||||
{
|
||||
try
|
||||
{
|
||||
// SOC 相关参数
|
||||
config.MustChargeSoc = (double)numMustChargeSoc.Value;
|
||||
config.IdleChargeSoc = (double)numIdleChargeSoc.Value;
|
||||
config.TaskAvailableSoc = (double)numTaskAvailableSoc.Value;
|
||||
config.FullChargeSoc = (double)numFullChargeSoc.Value;
|
||||
config.AllowInterruptSoc = (double)numAllowInterruptSoc.Value;
|
||||
|
||||
// 时间相关参数
|
||||
config.IdleChargeSeconds = (double)numIdleChargeSeconds.Value;
|
||||
config.IdleSeconds = (double)numIdleSeconds.Value;
|
||||
config.MustChargeSeconds = (double)numMustChargeSeconds.Value;
|
||||
config.TopUpMinutes = (double)numTopUpMinutes.Value;
|
||||
|
||||
// 任务相关参数
|
||||
config.MinAllowFreeCarToChargeTaskCnt = (int)numMinAllowFreeCarToChargeTaskCnt.Value;
|
||||
|
||||
// 开关参数
|
||||
config.AllowInterruptTask = chkAllowInterruptTask.Checked;
|
||||
config.UseLowerSocForCharge = chkUseLowerSocForCharge.Checked;
|
||||
config.EnableErrorChargeDetection = chkEnableErrorChargeDetection.Checked;
|
||||
config.UseChargeSiteFilter = chkUseChargeSiteFilter.Checked;
|
||||
|
||||
// 保存到文件
|
||||
configService.SaveConfig(config);
|
||||
|
||||
lblStatus.Text = "配置保存成功";
|
||||
lblStatus.ForeColor = Color.Green;
|
||||
|
||||
MessageBox.Show("充电策略配置保存成功!", "成功",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
_config = ConfigService.LoadConfig();
|
||||
ApplyConfigToUi(_config);
|
||||
_status = "配置加载成功";
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"保存配置失败: {ex.Message}", "错误",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
lblStatus.Text = "配置保存失败";
|
||||
lblStatus.ForeColor = Color.Red;
|
||||
CycleUiHelper.Alert("错误", $"加载配置失败: {ex.Message}");
|
||||
_status = "配置加载失败";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 恢复默认配置
|
||||
/// </summary>
|
||||
private void RestoreDefaults()
|
||||
private static void ApplyConfigToUi(ChargeStrategyConfig config)
|
||||
{
|
||||
var result = MessageBox.Show(
|
||||
"确定要恢复默认配置吗?当前配置将被覆盖。",
|
||||
"确认恢复",
|
||||
MessageBoxButtons.YesNo,
|
||||
MessageBoxIcon.Question);
|
||||
_mustChargeSoc = (float)config.MustChargeSoc;
|
||||
_idleChargeSoc = (float)config.IdleChargeSoc;
|
||||
_taskAvailableSoc = (float)config.TaskAvailableSoc;
|
||||
_fullChargeSoc = (float)config.FullChargeSoc;
|
||||
_allowInterruptSoc = (float)config.AllowInterruptSoc;
|
||||
|
||||
if (result == DialogResult.Yes)
|
||||
{
|
||||
config = ChargeStrategyConfig.CreateDefault();
|
||||
LoadConfig(true);
|
||||
lblStatus.Text = "已恢复默认配置(未保存)";
|
||||
lblStatus.ForeColor = Color.Blue;
|
||||
}
|
||||
_idleChargeSeconds = (float)config.IdleChargeSeconds;
|
||||
_idleSeconds = (float)config.IdleSeconds;
|
||||
_mustChargeSeconds = (float)config.MustChargeSeconds;
|
||||
_topUpMinutes = (float)config.TopUpMinutes;
|
||||
|
||||
_minAllowFreeCarToChargeTaskCnt = config.MinAllowFreeCarToChargeTaskCnt;
|
||||
|
||||
_allowInterruptTask = config.AllowInterruptTask;
|
||||
_useLowerSocForCharge = config.UseLowerSocForCharge;
|
||||
_enableErrorChargeDetection = config.EnableErrorChargeDetection;
|
||||
_useChargeSiteFilter = config.UseChargeSiteFilter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证配置参数
|
||||
/// </summary>
|
||||
private bool ValidateConfig()
|
||||
private static void ApplyUiToConfig()
|
||||
{
|
||||
// 验证 SOC 范围
|
||||
if (numMustChargeSoc.Value >= numIdleChargeSoc.Value)
|
||||
_config.MustChargeSoc = _mustChargeSoc;
|
||||
_config.IdleChargeSoc = _idleChargeSoc;
|
||||
_config.TaskAvailableSoc = _taskAvailableSoc;
|
||||
_config.FullChargeSoc = _fullChargeSoc;
|
||||
_config.AllowInterruptSoc = _allowInterruptSoc;
|
||||
|
||||
_config.IdleChargeSeconds = _idleChargeSeconds;
|
||||
_config.IdleSeconds = _idleSeconds;
|
||||
_config.MustChargeSeconds = _mustChargeSeconds;
|
||||
_config.TopUpMinutes = _topUpMinutes;
|
||||
|
||||
_config.MinAllowFreeCarToChargeTaskCnt = _minAllowFreeCarToChargeTaskCnt;
|
||||
|
||||
_config.AllowInterruptTask = _allowInterruptTask;
|
||||
_config.UseLowerSocForCharge = _useLowerSocForCharge;
|
||||
_config.EnableErrorChargeDetection = _enableErrorChargeDetection;
|
||||
_config.UseChargeSiteFilter = _useChargeSiteFilter;
|
||||
}
|
||||
|
||||
/// <summary>验证 SOC 阈值之间的逻辑关系(保存前)。</summary>
|
||||
private static bool ValidateSocRanges(out string errorMessage)
|
||||
{
|
||||
if (_mustChargeSoc >= _idleChargeSoc)
|
||||
{
|
||||
MessageBox.Show("必充电量必须小于空闲充电电量", "验证失败",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
errorMessage = "必充电量必须小于空闲充电电量";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (numTaskAvailableSoc.Value <= numMustChargeSoc.Value)
|
||||
if (_taskAvailableSoc <= _mustChargeSoc)
|
||||
{
|
||||
MessageBox.Show("任务可用电量必须大于必充电量", "验证失败",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
errorMessage = "任务可用电量必须大于必充电量";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (numFullChargeSoc.Value < numIdleChargeSoc.Value)
|
||||
if (_fullChargeSoc < _idleChargeSoc)
|
||||
{
|
||||
MessageBox.Show("满电电量必须大于等于空闲充电电量", "验证失败",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
errorMessage = "满电电量必须大于等于空闲充电电量";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (numAllowInterruptSoc.Value <= numMustChargeSoc.Value)
|
||||
if (_allowInterruptSoc <= _mustChargeSoc)
|
||||
{
|
||||
MessageBox.Show("允许中断电量必须大于必充电量", "验证失败",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
errorMessage = "允许中断电量必须大于必充电量";
|
||||
return false;
|
||||
}
|
||||
|
||||
errorMessage = string.Empty;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ==================== 事件处理 ====================
|
||||
|
||||
private void btnSave_Click(object sender, EventArgs e)
|
||||
private static void TrySave(bool closeAfterSave)
|
||||
{
|
||||
if (ValidateConfig())
|
||||
ApplyUiToConfig();
|
||||
|
||||
if (!ValidateSocRanges(out var socError))
|
||||
{
|
||||
SaveConfig();
|
||||
CycleUiHelper.Alert("验证失败", socError);
|
||||
_status = "配置保存失败";
|
||||
_panel?.Repaint();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ConfigService.SaveConfig(_config);
|
||||
_status = "配置保存成功";
|
||||
CycleUiHelper.Alert("成功", "充电策略配置保存成功!");
|
||||
if (closeAfterSave)
|
||||
{
|
||||
_panel?.Exit();
|
||||
_panel = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_panel?.Repaint();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
CycleUiHelper.Alert("错误", $"保存配置失败: {ex.Message}");
|
||||
_status = "配置保存失败";
|
||||
_panel?.Repaint();
|
||||
}
|
||||
}
|
||||
|
||||
private void btnCancel_Click(object sender, EventArgs e)
|
||||
private static void RestoreDefaults()
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void btnRestoreDefaults_Click(object sender, EventArgs e)
|
||||
{
|
||||
RestoreDefaults();
|
||||
}
|
||||
|
||||
private void btnApply_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (ValidateConfig())
|
||||
CycleUiHelper.ConfirmThen("确定要恢复默认配置吗?当前配置将被覆盖。", () =>
|
||||
{
|
||||
SaveConfig();
|
||||
}
|
||||
_config = ChargeStrategyConfig.CreateDefault();
|
||||
ApplyConfigToUi(_config);
|
||||
_status = "已恢复默认配置(未保存)";
|
||||
_panel?.Repaint();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,376 +0,0 @@
|
||||
namespace StandardScene.Charge
|
||||
{
|
||||
partial class CommunicationMonitorForm
|
||||
{
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
this.splitContainer = new System.Windows.Forms.SplitContainer();
|
||||
this.pnlLeft = new System.Windows.Forms.Panel();
|
||||
this.dgvMessages = new System.Windows.Forms.DataGridView();
|
||||
this.colTime = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.colDirection = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.colIpAddress = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.colPort = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.colLength = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.colRawData = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.colStationId = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.type = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.pnlLeftTop = new System.Windows.Forms.Panel();
|
||||
this.button1 = new System.Windows.Forms.Button();
|
||||
this.btnClear = new System.Windows.Forms.Button();
|
||||
this.btnRefresh = new System.Windows.Forms.Button();
|
||||
this.lblStatistics = new System.Windows.Forms.Label();
|
||||
this.cmbIpFilter = new System.Windows.Forms.ComboBox();
|
||||
this.lblIpFilter = new System.Windows.Forms.Label();
|
||||
this.pnlRight = new System.Windows.Forms.Panel();
|
||||
this.txtParsedData = new System.Windows.Forms.TextBox();
|
||||
this.pnlRightTop = new System.Windows.Forms.Panel();
|
||||
this.btnClose = new System.Windows.Forms.Button();
|
||||
this.lblParsedTitle = new System.Windows.Forms.Label();
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
|
||||
this.splitContainer.Panel1.SuspendLayout();
|
||||
this.splitContainer.Panel2.SuspendLayout();
|
||||
this.splitContainer.SuspendLayout();
|
||||
this.pnlLeft.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.dgvMessages)).BeginInit();
|
||||
this.pnlLeftTop.SuspendLayout();
|
||||
this.pnlRight.SuspendLayout();
|
||||
this.pnlRightTop.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// splitContainer
|
||||
//
|
||||
this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.splitContainer.Location = new System.Drawing.Point(0, 0);
|
||||
this.splitContainer.Name = "splitContainer";
|
||||
//
|
||||
// splitContainer.Panel1
|
||||
//
|
||||
this.splitContainer.Panel1.Controls.Add(this.pnlLeft);
|
||||
//
|
||||
// splitContainer.Panel2
|
||||
//
|
||||
this.splitContainer.Panel2.Controls.Add(this.pnlRight);
|
||||
this.splitContainer.Size = new System.Drawing.Size(1400, 800);
|
||||
this.splitContainer.SplitterDistance = 850;
|
||||
this.splitContainer.TabIndex = 0;
|
||||
//
|
||||
// pnlLeft
|
||||
//
|
||||
this.pnlLeft.Controls.Add(this.dgvMessages);
|
||||
this.pnlLeft.Controls.Add(this.pnlLeftTop);
|
||||
this.pnlLeft.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pnlLeft.Location = new System.Drawing.Point(0, 0);
|
||||
this.pnlLeft.Name = "pnlLeft";
|
||||
this.pnlLeft.Size = new System.Drawing.Size(850, 800);
|
||||
this.pnlLeft.TabIndex = 0;
|
||||
//
|
||||
// dgvMessages
|
||||
//
|
||||
this.dgvMessages.AllowUserToAddRows = false;
|
||||
this.dgvMessages.AllowUserToDeleteRows = false;
|
||||
this.dgvMessages.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
|
||||
this.dgvMessages.BackgroundColor = System.Drawing.Color.White;
|
||||
this.dgvMessages.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
|
||||
dataGridViewCellStyle1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(81)))), ((int)(((byte)(181)))));
|
||||
dataGridViewCellStyle1.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
dataGridViewCellStyle1.ForeColor = System.Drawing.Color.White;
|
||||
dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight;
|
||||
dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
|
||||
this.dgvMessages.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1;
|
||||
this.dgvMessages.ColumnHeadersHeight = 35;
|
||||
this.dgvMessages.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
|
||||
this.colTime,
|
||||
this.colDirection,
|
||||
this.colIpAddress,
|
||||
this.colPort,
|
||||
this.colLength,
|
||||
this.colRawData,
|
||||
this.colStationId,
|
||||
this.type});
|
||||
this.dgvMessages.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.dgvMessages.EnableHeadersVisualStyles = false;
|
||||
this.dgvMessages.GridColor = System.Drawing.Color.LightGray;
|
||||
this.dgvMessages.Location = new System.Drawing.Point(0, 80);
|
||||
this.dgvMessages.MultiSelect = false;
|
||||
this.dgvMessages.Name = "dgvMessages";
|
||||
this.dgvMessages.ReadOnly = true;
|
||||
this.dgvMessages.RowHeadersVisible = false;
|
||||
this.dgvMessages.RowHeadersWidth = 51;
|
||||
this.dgvMessages.RowTemplate.Height = 30;
|
||||
this.dgvMessages.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
|
||||
this.dgvMessages.Size = new System.Drawing.Size(850, 720);
|
||||
this.dgvMessages.TabIndex = 1;
|
||||
this.dgvMessages.SelectionChanged += new System.EventHandler(this.dgvMessages_SelectionChanged);
|
||||
//
|
||||
// colTime
|
||||
//
|
||||
this.colTime.FillWeight = 80F;
|
||||
this.colTime.HeaderText = "时间";
|
||||
this.colTime.MinimumWidth = 6;
|
||||
this.colTime.Name = "colTime";
|
||||
this.colTime.ReadOnly = true;
|
||||
//
|
||||
// colDirection
|
||||
//
|
||||
this.colDirection.FillWeight = 50F;
|
||||
this.colDirection.HeaderText = "方向";
|
||||
this.colDirection.MinimumWidth = 6;
|
||||
this.colDirection.Name = "colDirection";
|
||||
this.colDirection.ReadOnly = true;
|
||||
//
|
||||
// colIpAddress
|
||||
//
|
||||
this.colIpAddress.FillWeight = 80F;
|
||||
this.colIpAddress.HeaderText = "IP地址";
|
||||
this.colIpAddress.MinimumWidth = 6;
|
||||
this.colIpAddress.Name = "colIpAddress";
|
||||
this.colIpAddress.ReadOnly = true;
|
||||
//
|
||||
// colPort
|
||||
//
|
||||
this.colPort.FillWeight = 50F;
|
||||
this.colPort.HeaderText = "端口";
|
||||
this.colPort.MinimumWidth = 6;
|
||||
this.colPort.Name = "colPort";
|
||||
this.colPort.ReadOnly = true;
|
||||
//
|
||||
// colLength
|
||||
//
|
||||
this.colLength.FillWeight = 50F;
|
||||
this.colLength.HeaderText = "长度";
|
||||
this.colLength.MinimumWidth = 6;
|
||||
this.colLength.Name = "colLength";
|
||||
this.colLength.ReadOnly = true;
|
||||
//
|
||||
// colRawData
|
||||
//
|
||||
this.colRawData.FillWeight = 200F;
|
||||
this.colRawData.HeaderText = "原始数据";
|
||||
this.colRawData.MinimumWidth = 6;
|
||||
this.colRawData.Name = "colRawData";
|
||||
this.colRawData.ReadOnly = true;
|
||||
//
|
||||
// colStationId
|
||||
//
|
||||
this.colStationId.FillWeight = 80F;
|
||||
this.colStationId.HeaderText = "充电桩";
|
||||
this.colStationId.MinimumWidth = 6;
|
||||
this.colStationId.Name = "colStationId";
|
||||
this.colStationId.ReadOnly = true;
|
||||
//
|
||||
// type
|
||||
//
|
||||
this.type.HeaderText = "协议类型";
|
||||
this.type.MinimumWidth = 6;
|
||||
this.type.Name = "type";
|
||||
this.type.ReadOnly = true;
|
||||
//
|
||||
// pnlLeftTop
|
||||
//
|
||||
this.pnlLeftTop.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(250)))), ((int)(((byte)(250)))), ((int)(((byte)(250)))));
|
||||
this.pnlLeftTop.Controls.Add(this.button1);
|
||||
this.pnlLeftTop.Controls.Add(this.btnClear);
|
||||
this.pnlLeftTop.Controls.Add(this.btnRefresh);
|
||||
this.pnlLeftTop.Controls.Add(this.lblStatistics);
|
||||
this.pnlLeftTop.Controls.Add(this.cmbIpFilter);
|
||||
this.pnlLeftTop.Controls.Add(this.lblIpFilter);
|
||||
this.pnlLeftTop.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.pnlLeftTop.Location = new System.Drawing.Point(0, 0);
|
||||
this.pnlLeftTop.Name = "pnlLeftTop";
|
||||
this.pnlLeftTop.Padding = new System.Windows.Forms.Padding(10);
|
||||
this.pnlLeftTop.Size = new System.Drawing.Size(850, 80);
|
||||
this.pnlLeftTop.TabIndex = 0;
|
||||
//
|
||||
// button1
|
||||
//
|
||||
this.button1.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.button1.Location = new System.Drawing.Point(546, 16);
|
||||
this.button1.Name = "button1";
|
||||
this.button1.Size = new System.Drawing.Size(80, 32);
|
||||
this.button1.TabIndex = 5;
|
||||
this.button1.Text = "暂停";
|
||||
this.button1.UseVisualStyleBackColor = true;
|
||||
this.button1.Click += new System.EventHandler(this.button1_Click);
|
||||
//
|
||||
// btnClear
|
||||
//
|
||||
this.btnClear.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.btnClear.Location = new System.Drawing.Point(460, 15);
|
||||
this.btnClear.Name = "btnClear";
|
||||
this.btnClear.Size = new System.Drawing.Size(80, 32);
|
||||
this.btnClear.TabIndex = 4;
|
||||
this.btnClear.Text = "清空";
|
||||
this.btnClear.UseVisualStyleBackColor = true;
|
||||
this.btnClear.Click += new System.EventHandler(this.btnClear_Click);
|
||||
//
|
||||
// btnRefresh
|
||||
//
|
||||
this.btnRefresh.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.btnRefresh.Location = new System.Drawing.Point(370, 15);
|
||||
this.btnRefresh.Name = "btnRefresh";
|
||||
this.btnRefresh.Size = new System.Drawing.Size(80, 32);
|
||||
this.btnRefresh.TabIndex = 3;
|
||||
this.btnRefresh.Text = "刷新";
|
||||
this.btnRefresh.UseVisualStyleBackColor = true;
|
||||
this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
|
||||
//
|
||||
// lblStatistics
|
||||
//
|
||||
this.lblStatistics.AutoSize = true;
|
||||
this.lblStatistics.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.lblStatistics.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100)))));
|
||||
this.lblStatistics.Location = new System.Drawing.Point(13, 52);
|
||||
this.lblStatistics.Name = "lblStatistics";
|
||||
this.lblStatistics.Size = new System.Drawing.Size(115, 20);
|
||||
this.lblStatistics.TabIndex = 2;
|
||||
this.lblStatistics.Text = "显示: 0 | 总数: 0";
|
||||
//
|
||||
// cmbIpFilter
|
||||
//
|
||||
this.cmbIpFilter.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.cmbIpFilter.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.cmbIpFilter.FormattingEnabled = true;
|
||||
this.cmbIpFilter.Location = new System.Drawing.Point(100, 17);
|
||||
this.cmbIpFilter.Name = "cmbIpFilter";
|
||||
this.cmbIpFilter.Size = new System.Drawing.Size(250, 28);
|
||||
this.cmbIpFilter.TabIndex = 1;
|
||||
this.cmbIpFilter.SelectedIndexChanged += new System.EventHandler(this.cmbIpFilter_SelectedIndexChanged);
|
||||
//
|
||||
// lblIpFilter
|
||||
//
|
||||
this.lblIpFilter.AutoSize = true;
|
||||
this.lblIpFilter.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.lblIpFilter.Location = new System.Drawing.Point(13, 21);
|
||||
this.lblIpFilter.Name = "lblIpFilter";
|
||||
this.lblIpFilter.Size = new System.Drawing.Size(67, 20);
|
||||
this.lblIpFilter.TabIndex = 0;
|
||||
this.lblIpFilter.Text = "IP筛选:";
|
||||
//
|
||||
// pnlRight
|
||||
//
|
||||
this.pnlRight.Controls.Add(this.txtParsedData);
|
||||
this.pnlRight.Controls.Add(this.pnlRightTop);
|
||||
this.pnlRight.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pnlRight.Location = new System.Drawing.Point(0, 0);
|
||||
this.pnlRight.Name = "pnlRight";
|
||||
this.pnlRight.Size = new System.Drawing.Size(546, 800);
|
||||
this.pnlRight.TabIndex = 0;
|
||||
//
|
||||
// txtParsedData
|
||||
//
|
||||
this.txtParsedData.BackColor = System.Drawing.Color.White;
|
||||
this.txtParsedData.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.txtParsedData.Font = new System.Drawing.Font("Consolas", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.txtParsedData.Location = new System.Drawing.Point(0, 60);
|
||||
this.txtParsedData.Multiline = true;
|
||||
this.txtParsedData.Name = "txtParsedData";
|
||||
this.txtParsedData.ReadOnly = true;
|
||||
this.txtParsedData.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||
this.txtParsedData.Size = new System.Drawing.Size(546, 740);
|
||||
this.txtParsedData.TabIndex = 1;
|
||||
this.txtParsedData.WordWrap = false;
|
||||
//
|
||||
// pnlRightTop
|
||||
//
|
||||
this.pnlRightTop.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(250)))), ((int)(((byte)(250)))), ((int)(((byte)(250)))));
|
||||
this.pnlRightTop.Controls.Add(this.btnClose);
|
||||
this.pnlRightTop.Controls.Add(this.lblParsedTitle);
|
||||
this.pnlRightTop.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.pnlRightTop.Location = new System.Drawing.Point(0, 0);
|
||||
this.pnlRightTop.Name = "pnlRightTop";
|
||||
this.pnlRightTop.Padding = new System.Windows.Forms.Padding(10);
|
||||
this.pnlRightTop.Size = new System.Drawing.Size(546, 60);
|
||||
this.pnlRightTop.TabIndex = 0;
|
||||
//
|
||||
// btnClose
|
||||
//
|
||||
this.btnClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btnClose.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.btnClose.Location = new System.Drawing.Point(446, 15);
|
||||
this.btnClose.Name = "btnClose";
|
||||
this.btnClose.Size = new System.Drawing.Size(80, 32);
|
||||
this.btnClose.TabIndex = 1;
|
||||
this.btnClose.Text = "关闭";
|
||||
this.btnClose.UseVisualStyleBackColor = true;
|
||||
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
|
||||
//
|
||||
// lblParsedTitle
|
||||
//
|
||||
this.lblParsedTitle.AutoSize = true;
|
||||
this.lblParsedTitle.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.lblParsedTitle.Location = new System.Drawing.Point(13, 20);
|
||||
this.lblParsedTitle.Name = "lblParsedTitle";
|
||||
this.lblParsedTitle.Size = new System.Drawing.Size(112, 24);
|
||||
this.lblParsedTitle.TabIndex = 0;
|
||||
this.lblParsedTitle.Text = "报文数据解析";
|
||||
//
|
||||
// CommunicationMonitorForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(1400, 800);
|
||||
this.Controls.Add(this.splitContainer);
|
||||
this.Name = "CommunicationMonitorForm";
|
||||
this.Text = "通讯监控";
|
||||
this.Load += new System.EventHandler(this.CommunicationMonitorForm_Load);
|
||||
this.splitContainer.Panel1.ResumeLayout(false);
|
||||
this.splitContainer.Panel2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
|
||||
this.splitContainer.ResumeLayout(false);
|
||||
this.pnlLeft.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.dgvMessages)).EndInit();
|
||||
this.pnlLeftTop.ResumeLayout(false);
|
||||
this.pnlLeftTop.PerformLayout();
|
||||
this.pnlRight.ResumeLayout(false);
|
||||
this.pnlRight.PerformLayout();
|
||||
this.pnlRightTop.ResumeLayout(false);
|
||||
this.pnlRightTop.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.SplitContainer splitContainer;
|
||||
private System.Windows.Forms.Panel pnlLeft;
|
||||
private System.Windows.Forms.DataGridView dgvMessages;
|
||||
private System.Windows.Forms.Panel pnlLeftTop;
|
||||
private System.Windows.Forms.ComboBox cmbIpFilter;
|
||||
private System.Windows.Forms.Label lblIpFilter;
|
||||
private System.Windows.Forms.Panel pnlRight;
|
||||
private System.Windows.Forms.TextBox txtParsedData;
|
||||
private System.Windows.Forms.Panel pnlRightTop;
|
||||
private System.Windows.Forms.Label lblParsedTitle;
|
||||
private System.Windows.Forms.Label lblStatistics;
|
||||
private System.Windows.Forms.Button btnRefresh;
|
||||
private System.Windows.Forms.Button btnClear;
|
||||
private System.Windows.Forms.Button btnClose;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn colTime;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn colDirection;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn colIpAddress;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn colPort;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn colLength;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn colRawData;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn colStationId;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn type;
|
||||
private System.Windows.Forms.Button button1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,108 +2,298 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using System.Text;
|
||||
using CycleGUI;
|
||||
using StandardScene.Utils;
|
||||
|
||||
namespace StandardScene.Charge
|
||||
{
|
||||
/// <summary>
|
||||
/// 通讯监控窗体
|
||||
/// 通讯监控面板(CycleGUI 版,替代原 WinForms 窗体)。
|
||||
/// <list type="bullet">
|
||||
/// <item>单实例:再次打开则把已有面板置前。</item>
|
||||
/// <item>订阅 <see cref="CommunicationMessageService.MessageAdded"/>,批量刷新 UI(500ms 节流),最多显示 100 行。</item>
|
||||
/// <item>支持 IP 筛选、暂停/继续、清空(二次确认)、选中报文解析详情。</item>
|
||||
/// </list>
|
||||
/// 保留可实例化 + <see cref="Show"/> 以兼容既有调用。
|
||||
/// </summary>
|
||||
public partial class CommunicationMonitorForm : Form
|
||||
public class CommunicationMonitorForm
|
||||
{
|
||||
private readonly CommunicationMessageService messageService;
|
||||
private bool isFormLoaded = false;
|
||||
private bool isFormMessageStop = false;
|
||||
private const int MaxDisplayRows = 100;
|
||||
private const int UiBatchSize = 20;
|
||||
private const int StatsRefreshMs = 500;
|
||||
private readonly Queue<CommunicationMessage> pendingMessages = new Queue<CommunicationMessage>();
|
||||
private readonly object pendingMessagesLock = new object();
|
||||
private readonly Timer uiFlushTimer;
|
||||
private readonly Timer statsRefreshTimer;
|
||||
private bool pendingStatsRefresh = false;
|
||||
private int lastDisplayCountForStats = 0;
|
||||
public CommunicationMonitorForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
messageService = CommunicationMessageService.Instance;
|
||||
uiFlushTimer = new Timer { Interval = 500 };
|
||||
uiFlushTimer.Tick += UiFlushTimer_Tick;
|
||||
statsRefreshTimer = new Timer { Interval = StatsRefreshMs };
|
||||
statsRefreshTimer.Tick += StatsRefreshTimer_Tick;
|
||||
private const string TableId = "comm-monitor-msgs";
|
||||
|
||||
// 订阅窗体关闭事件
|
||||
this.FormClosing += CommunicationMonitorForm_FormClosing;
|
||||
private static readonly Color SendRowColor = Color.FromArgb(232, 245, 233);
|
||||
private static readonly Color ReceiveRowColor = Color.FromArgb(227, 242, 253);
|
||||
private static readonly Color SelectedRowColor = Color.FromArgb(255, 249, 196);
|
||||
|
||||
private static readonly CommunicationMessageService MessageService = CommunicationMessageService.Instance;
|
||||
|
||||
private static Panel _panel;
|
||||
private static bool _subscribed;
|
||||
private static bool _paused;
|
||||
private static int _selectedIpIndex;
|
||||
private static string[] _ipOptions = { "全部" };
|
||||
private static int _selectedRowIndex = -1;
|
||||
private static string _parsedText = "";
|
||||
private static string _statsText = "";
|
||||
|
||||
private static List<CommunicationMessage> _displayMessages = new List<CommunicationMessage>();
|
||||
private static readonly Queue<CommunicationMessage> PendingMessages = new Queue<CommunicationMessage>();
|
||||
private static readonly object PendingLock = new object();
|
||||
|
||||
private static DateTime _lastStatsRefresh = DateTime.MinValue;
|
||||
private static bool _pendingStatsRefresh;
|
||||
|
||||
/// <summary>打开(或置前)通讯监控面板。兼容原 <c>new CommunicationMonitorForm().Show()</c> 调用方式。</summary>
|
||||
public void Show() => Open();
|
||||
|
||||
/// <summary>打开(或置前)通讯监控面板。</summary>
|
||||
public static void Open()
|
||||
{
|
||||
if (_panel != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_panel.BringToFront();
|
||||
return;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_panel = null;
|
||||
}
|
||||
}
|
||||
|
||||
_paused = false;
|
||||
_selectedRowIndex = -1;
|
||||
_parsedText = "";
|
||||
RefreshIpFilter();
|
||||
ReloadFromService();
|
||||
|
||||
var panel = GUI.DeclarePanel()
|
||||
.ShowTitle("通讯监控")
|
||||
.SetDefaultDocking(Panel.Docking.None)
|
||||
.InitSize(1400, 800)
|
||||
.InitPos(false, 0, 0, 0.5f, 0.5f, 0.5f, 0.5f);
|
||||
_panel = panel;
|
||||
panel.IfTerminalQuit(() =>
|
||||
{
|
||||
Unsubscribe();
|
||||
_panel = null;
|
||||
});
|
||||
|
||||
Subscribe();
|
||||
|
||||
panel.Define(pb =>
|
||||
{
|
||||
if (pb.Closing())
|
||||
{
|
||||
Unsubscribe();
|
||||
panel.Exit();
|
||||
_panel = null;
|
||||
return;
|
||||
}
|
||||
|
||||
FlushPendingBatch();
|
||||
|
||||
if (pb.DropdownBox("IP筛选", _ipOptions, ref _selectedIpIndex))
|
||||
ReloadFromService();
|
||||
|
||||
pb.SameLine(16);
|
||||
if (pb.Button(_paused ? "继续" : "暂停", distinct: "comm-pause"))
|
||||
_paused = !_paused;
|
||||
pb.SameLine(8);
|
||||
if (pb.Button("刷新", distinct: "comm-refresh"))
|
||||
{
|
||||
RefreshIpFilter();
|
||||
ReloadFromService();
|
||||
RequestStatisticsRefresh();
|
||||
}
|
||||
pb.SameLine(8);
|
||||
if (pb.Button("清空", distinct: "comm-clear"))
|
||||
{
|
||||
CycleUiHelper.ConfirmThen("确定要清空所有报文记录吗?", () =>
|
||||
{
|
||||
MessageService.Clear();
|
||||
lock (PendingLock)
|
||||
PendingMessages.Clear();
|
||||
RefreshIpFilter();
|
||||
_displayMessages.Clear();
|
||||
_selectedRowIndex = -1;
|
||||
_parsedText = "";
|
||||
RequestStatisticsRefresh();
|
||||
});
|
||||
}
|
||||
pb.SameLine(8);
|
||||
if (pb.Button("关闭", distinct: "comm-close"))
|
||||
{
|
||||
Unsubscribe();
|
||||
panel.Exit();
|
||||
_panel = null;
|
||||
return;
|
||||
}
|
||||
|
||||
MaybeRefreshStatistics();
|
||||
pb.Label(_statsText);
|
||||
|
||||
pb.Table(TableId,
|
||||
new[] { "时间", "方向", "IP地址", "端口", "长度", "原始数据", "站点", "类型", "操作" },
|
||||
_displayMessages.Count, (row, i) =>
|
||||
{
|
||||
var msg = _displayMessages[i];
|
||||
row.SetColor(_selectedRowIndex == i
|
||||
? SelectedRowColor
|
||||
: msg.Direction == MessageDirection.Send ? SendRowColor : ReceiveRowColor);
|
||||
|
||||
row.Label($"{msg.Timestamp:HH:mm:ss.fff}");
|
||||
row.Label(msg.Direction == MessageDirection.Send ? "发送" : "接收");
|
||||
row.Label(msg.IpAddress ?? "");
|
||||
row.Label($"{msg.Port}");
|
||||
row.Label($"{msg.Length}");
|
||||
row.Label(TruncateRawData(msg.RawData));
|
||||
row.Label(string.IsNullOrEmpty(msg.StationId) ? "-" : msg.StationId);
|
||||
row.Label(msg.Type ?? "");
|
||||
|
||||
if (row.ButtonGroup(new[] { "解析" }, new[] { "解析该报文" }) == 0)
|
||||
{
|
||||
_selectedRowIndex = i;
|
||||
_parsedText = BuildParsedText(msg);
|
||||
}
|
||||
}, height: 20, enableSearch: true);
|
||||
|
||||
pb.SeparatorText("报文解析");
|
||||
pb.SelectableText(null, _parsedText ?? "", copyButton: true);
|
||||
|
||||
pb.Panel.Repaint(repaintTimeMs: 500);
|
||||
});
|
||||
}
|
||||
|
||||
private void CommunicationMonitorForm_Load(object sender, EventArgs e)
|
||||
private static void Subscribe()
|
||||
{
|
||||
if (_subscribed)
|
||||
return;
|
||||
MessageService.MessageAdded += OnMessageAdded;
|
||||
_subscribed = true;
|
||||
}
|
||||
|
||||
private static void Unsubscribe()
|
||||
{
|
||||
if (!_subscribed)
|
||||
return;
|
||||
MessageService.MessageAdded -= OnMessageAdded;
|
||||
_subscribed = false;
|
||||
lock (PendingLock)
|
||||
PendingMessages.Clear();
|
||||
}
|
||||
|
||||
private static void OnMessageAdded(object sender, CommunicationMessage message)
|
||||
{
|
||||
if (!_subscribed || message == null)
|
||||
return;
|
||||
|
||||
lock (PendingLock)
|
||||
PendingMessages.Enqueue(message);
|
||||
|
||||
_panel?.Repaint();
|
||||
}
|
||||
|
||||
/// <summary>定时批量刷新 UI,避免每条报文都抢占渲染线程。</summary>
|
||||
private static void FlushPendingBatch()
|
||||
{
|
||||
if (_paused)
|
||||
return;
|
||||
|
||||
List<CommunicationMessage> batch = null;
|
||||
lock (PendingLock)
|
||||
{
|
||||
if (PendingMessages.Count == 0)
|
||||
return;
|
||||
|
||||
int count = Math.Min(UiBatchSize, PendingMessages.Count);
|
||||
batch = new List<CommunicationMessage>(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
batch.Add(PendingMessages.Dequeue());
|
||||
}
|
||||
|
||||
if (batch == null || batch.Count == 0)
|
||||
return;
|
||||
|
||||
var filter = SelectedIpFilter();
|
||||
bool displayChanged = false;
|
||||
|
||||
foreach (var message in batch)
|
||||
{
|
||||
EnsureIpInFilter(message.IpAddress);
|
||||
if (string.IsNullOrEmpty(filter) || filter == "全部" || filter == message.IpAddress)
|
||||
{
|
||||
InsertMessageAtTop(message);
|
||||
displayChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (displayChanged)
|
||||
RequestStatisticsRefresh();
|
||||
}
|
||||
|
||||
private static void InsertMessageAtTop(CommunicationMessage msg)
|
||||
{
|
||||
_displayMessages.Insert(0, msg);
|
||||
while (_displayMessages.Count > MaxDisplayRows)
|
||||
_displayMessages.RemoveAt(_displayMessages.Count - 1);
|
||||
|
||||
if (_selectedRowIndex >= 0)
|
||||
_selectedRowIndex++;
|
||||
}
|
||||
|
||||
private static void ReloadFromService()
|
||||
{
|
||||
try
|
||||
{
|
||||
InitializeForm();
|
||||
LoadMessages();
|
||||
var filter = SelectedIpFilter();
|
||||
var messages = string.IsNullOrEmpty(filter) || filter == "全部"
|
||||
? MessageService.GetAllMessages()
|
||||
: MessageService.GetMessagesByIp(filter);
|
||||
|
||||
// 标记窗体已加载完成
|
||||
isFormLoaded = true;
|
||||
uiFlushTimer.Start();
|
||||
statsRefreshTimer.Start();
|
||||
|
||||
// 在窗体加载完成后再订阅报文添加事件(避免在初始化期间触发)
|
||||
messageService.MessageAdded += OnMessageAdded;
|
||||
_displayMessages = messages.Take(MaxDisplayRows).ToList();
|
||||
_selectedRowIndex = -1;
|
||||
_parsedText = "";
|
||||
_pendingStatsRefresh = false;
|
||||
UpdateStatistics(_displayMessages.Count);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"窗体加载失败: {ex.Message}\r\n{ex.StackTrace}", "错误",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
_statsText = $"加载报文失败: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeForm()
|
||||
{
|
||||
this.Text = "通讯监控";
|
||||
this.Size = new Size(1400, 800);
|
||||
this.StartPosition = FormStartPosition.CenterScreen;
|
||||
this.MinimumSize = new Size(1200, 600);
|
||||
|
||||
// 初始化IP筛选下拉框
|
||||
RefreshIpFilter();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新IP筛选下拉框
|
||||
/// </summary>
|
||||
private void RefreshIpFilter()
|
||||
private static void RefreshIpFilter()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (cmbIpFilter == null || messageService == null)
|
||||
return;
|
||||
var selectedIp = SelectedIpFilter();
|
||||
var options = new List<string> { "全部" };
|
||||
|
||||
var selectedIp = cmbIpFilter.SelectedItem?.ToString();
|
||||
|
||||
cmbIpFilter.Items.Clear();
|
||||
cmbIpFilter.Items.Add("全部");
|
||||
|
||||
var ipAddresses = messageService.GetUniqueIpAddresses();
|
||||
var ipAddresses = MessageService.GetUniqueIpAddresses();
|
||||
if (ipAddresses != null)
|
||||
{
|
||||
foreach (var ip in ipAddresses)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ip))
|
||||
{
|
||||
cmbIpFilter.Items.Add(ip);
|
||||
}
|
||||
options.Add(ip);
|
||||
}
|
||||
}
|
||||
|
||||
// 恢复选中项
|
||||
if (!string.IsNullOrEmpty(selectedIp) && cmbIpFilter.Items.Contains(selectedIp))
|
||||
_ipOptions = options.ToArray();
|
||||
|
||||
if (!string.IsNullOrEmpty(selectedIp))
|
||||
{
|
||||
cmbIpFilter.SelectedItem = selectedIp;
|
||||
var idx = Array.IndexOf(_ipOptions, selectedIp);
|
||||
_selectedIpIndex = idx >= 0 ? idx : 0;
|
||||
}
|
||||
else if (cmbIpFilter.Items.Count > 0)
|
||||
else
|
||||
{
|
||||
cmbIpFilter.SelectedIndex = 0;
|
||||
_selectedIpIndex = 0;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -112,248 +302,83 @@ namespace StandardScene.Charge
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载报文列表
|
||||
/// </summary>
|
||||
private void LoadMessages()
|
||||
private static void EnsureIpInFilter(string ipAddress)
|
||||
{
|
||||
var layoutSuspended = false;
|
||||
try
|
||||
{
|
||||
if (dgvMessages == null|| isFormMessageStop)
|
||||
return;
|
||||
|
||||
var selectedIp = cmbIpFilter?.SelectedItem?.ToString();
|
||||
var messages = string.IsNullOrEmpty(selectedIp) || selectedIp == "全部"
|
||||
? messageService.GetAllMessages()
|
||||
: messageService.GetMessagesByIp(selectedIp);
|
||||
|
||||
dgvMessages.SuspendLayout();
|
||||
layoutSuspended = true;
|
||||
dgvMessages.Rows.Clear();
|
||||
|
||||
foreach (var msg in messages)
|
||||
{
|
||||
AddMessageRow(msg, false);
|
||||
}
|
||||
|
||||
UpdateStatistics(messages.Count);
|
||||
pendingStatsRefresh = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"加载报文失败: {ex.Message}", "错误",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (layoutSuspended && dgvMessages != null)
|
||||
{
|
||||
dgvMessages.ResumeLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定时批量刷新UI,避免每条报文都抢占UI线程
|
||||
/// </summary>
|
||||
private void UiFlushTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
if (!isFormLoaded || isFormMessageStop)
|
||||
if (string.IsNullOrWhiteSpace(ipAddress))
|
||||
return;
|
||||
|
||||
List<CommunicationMessage> batch = null;
|
||||
lock (pendingMessagesLock)
|
||||
{
|
||||
if (pendingMessages.Count == 0)
|
||||
return;
|
||||
|
||||
int count = Math.Min(UiBatchSize, pendingMessages.Count);
|
||||
batch = new List<CommunicationMessage>(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
batch.Add(pendingMessages.Dequeue());
|
||||
}
|
||||
}
|
||||
|
||||
if (batch == null || batch.Count == 0)
|
||||
if (_ipOptions.Contains(ipAddress))
|
||||
return;
|
||||
|
||||
dgvMessages.SuspendLayout();
|
||||
try
|
||||
{
|
||||
var selectedIp = cmbIpFilter?.SelectedItem?.ToString();
|
||||
bool displayChanged = false;
|
||||
|
||||
foreach (var message in batch)
|
||||
{
|
||||
EnsureIpInFilter(message.IpAddress);
|
||||
if (string.IsNullOrEmpty(selectedIp) || selectedIp == "全部" || selectedIp == message.IpAddress)
|
||||
{
|
||||
AddMessageRow(message, true);
|
||||
displayChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (displayChanged)
|
||||
{
|
||||
RequestStatisticsRefresh(dgvMessages.Rows.Count);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
dgvMessages.ResumeLayout();
|
||||
}
|
||||
var list = _ipOptions.ToList();
|
||||
list.Add(ipAddress);
|
||||
_ipOptions = list.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 统计信息低频刷新(500ms)
|
||||
/// </summary>
|
||||
private void StatsRefreshTimer_Tick(object sender, EventArgs e)
|
||||
private static string SelectedIpFilter()
|
||||
{
|
||||
if (!isFormLoaded || isFormMessageStop || !pendingStatsRefresh)
|
||||
if (_ipOptions == null || _ipOptions.Length == 0)
|
||||
return "全部";
|
||||
if (_selectedIpIndex < 0 || _selectedIpIndex >= _ipOptions.Length)
|
||||
return "全部";
|
||||
return _ipOptions[_selectedIpIndex];
|
||||
}
|
||||
|
||||
private static void RequestStatisticsRefresh()
|
||||
{
|
||||
_pendingStatsRefresh = true;
|
||||
}
|
||||
|
||||
/// <summary>统计信息低频刷新(500ms)。</summary>
|
||||
private static void MaybeRefreshStatistics()
|
||||
{
|
||||
if (!_pendingStatsRefresh)
|
||||
return;
|
||||
if (DateTime.Now - _lastStatsRefresh < TimeSpan.FromMilliseconds(StatsRefreshMs))
|
||||
return;
|
||||
|
||||
pendingStatsRefresh = false;
|
||||
UpdateStatistics(lastDisplayCountForStats);
|
||||
_pendingStatsRefresh = false;
|
||||
_lastStatsRefresh = DateTime.Now;
|
||||
UpdateStatistics(_displayMessages.Count);
|
||||
}
|
||||
|
||||
private void RequestStatisticsRefresh(int displayCount)
|
||||
{
|
||||
lastDisplayCountForStats = displayCount;
|
||||
pendingStatsRefresh = true;
|
||||
}
|
||||
|
||||
private void EnsureIpInFilter(string ipAddress)
|
||||
{
|
||||
if (cmbIpFilter == null || string.IsNullOrWhiteSpace(ipAddress))
|
||||
return;
|
||||
|
||||
if (!cmbIpFilter.Items.Contains(ipAddress))
|
||||
{
|
||||
cmbIpFilter.Items.Add(ipAddress);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向表格新增一条报文行(支持头部插入)
|
||||
/// </summary>
|
||||
private void AddMessageRow(CommunicationMessage msg, bool insertAtTop = true)
|
||||
{
|
||||
if (msg == null || dgvMessages == null)
|
||||
return;
|
||||
|
||||
DataGridViewRow row;
|
||||
if (insertAtTop)
|
||||
{
|
||||
dgvMessages.Rows.Insert(0,
|
||||
msg.Timestamp.ToString("HH:mm:ss.fff"),
|
||||
msg.Direction == MessageDirection.Send ? "发送" : "接收",
|
||||
msg.IpAddress,
|
||||
msg.Port,
|
||||
msg.Length,
|
||||
msg.RawData,
|
||||
msg.StationId ?? "-",
|
||||
msg.Type);
|
||||
row = dgvMessages.Rows[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
var index = dgvMessages.Rows.Add(
|
||||
msg.Timestamp.ToString("HH:mm:ss.fff"),
|
||||
msg.Direction == MessageDirection.Send ? "发送" : "接收",
|
||||
msg.IpAddress,
|
||||
msg.Port,
|
||||
msg.Length,
|
||||
msg.RawData,
|
||||
msg.StationId ?? "-",
|
||||
msg.Type);
|
||||
row = dgvMessages.Rows[index];
|
||||
}
|
||||
|
||||
if (msg.Direction == MessageDirection.Send)
|
||||
{
|
||||
row.DefaultCellStyle.BackColor = Color.FromArgb(232, 245, 233);
|
||||
row.DefaultCellStyle.ForeColor = Color.FromArgb(46, 125, 50);
|
||||
}
|
||||
else
|
||||
{
|
||||
row.DefaultCellStyle.BackColor = Color.FromArgb(227, 242, 253);
|
||||
row.DefaultCellStyle.ForeColor = Color.FromArgb(13, 71, 161);
|
||||
}
|
||||
|
||||
while (dgvMessages.Rows.Count > MaxDisplayRows)
|
||||
{
|
||||
dgvMessages.Rows.RemoveAt(dgvMessages.Rows.Count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新统计信息
|
||||
/// </summary>
|
||||
private void UpdateStatistics(int displayCount)
|
||||
private static void UpdateStatistics(int displayCount)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (lblStatistics == null || messageService == null)
|
||||
return;
|
||||
|
||||
var allMessages = messageService.GetAllMessages();
|
||||
var allMessages = MessageService.GetAllMessages();
|
||||
if (allMessages == null)
|
||||
{
|
||||
_statsText = "统计信息加载失败";
|
||||
return;
|
||||
}
|
||||
|
||||
var sendCount = allMessages.Count(m => m.Direction == MessageDirection.Send);
|
||||
var receiveCount = allMessages.Count(m => m.Direction == MessageDirection.Receive);
|
||||
|
||||
lblStatistics.Text = $"显示: {displayCount} | 总数: {allMessages.Count} | 发送: {sendCount} | 接收: {receiveCount}";
|
||||
_statsText = $"显示: {displayCount} | 总数: {allMessages.Count} | 发送: {sendCount} | 接收: {receiveCount}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"更新统计信息失败: {ex.Message}");
|
||||
if (lblStatistics != null)
|
||||
{
|
||||
lblStatistics.Text = "统计信息加载失败";
|
||||
}
|
||||
_statsText = "统计信息加载失败";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新报文添加事件处理(线程安全)
|
||||
/// </summary>
|
||||
private void OnMessageAdded(object sender, CommunicationMessage message)
|
||||
private static string TruncateRawData(string rawData, int maxLen = 48)
|
||||
{
|
||||
// 如果窗体还未加载完成,忽略此事件
|
||||
if (!isFormLoaded || isFormMessageStop)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
if (message == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock (pendingMessagesLock)
|
||||
{
|
||||
pendingMessages.Enqueue(message);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"处理新报文失败: {ex.Message}");
|
||||
}
|
||||
if (string.IsNullOrEmpty(rawData))
|
||||
return "";
|
||||
return rawData.Length <= maxLen ? rawData : rawData.Substring(0, maxLen) + "…";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析报文数据
|
||||
/// </summary>
|
||||
private void ParseMessage(CommunicationMessage message)
|
||||
private static string BuildParsedText(CommunicationMessage message)
|
||||
{
|
||||
if (message == null || txtParsedData == null)
|
||||
return;
|
||||
if (message == null)
|
||||
return "";
|
||||
|
||||
try
|
||||
{
|
||||
var parsed = new System.Text.StringBuilder();
|
||||
var parsed = new StringBuilder();
|
||||
parsed.AppendLine("=== 报文解析 ===");
|
||||
parsed.AppendLine($"时间: {message.Timestamp:yyyy-MM-dd HH:mm:ss.fff}");
|
||||
parsed.AppendLine($"方向: {(message.Direction == MessageDirection.Send ? "发送" : "接收")}");
|
||||
@@ -363,199 +388,43 @@ namespace StandardScene.Charge
|
||||
parsed.AppendLine();
|
||||
parsed.AppendLine("=== 原始数据 (HEX) ===");
|
||||
parsed.AppendLine(message.RawData);
|
||||
// parsed.AppendLine(FormatHexString(message.RawData));
|
||||
parsed.AppendLine();
|
||||
parsed.AppendLine("=== 数据解析 ===");
|
||||
|
||||
// TODO: 根据实际协议进行解析
|
||||
parsed.AppendLine();
|
||||
if (message.Direction== MessageDirection.Send)
|
||||
if (message.Direction == MessageDirection.Send)
|
||||
{
|
||||
var sendDate = messageService.ParseSendRawData(message.RawData, message.Type);
|
||||
var sendData = MessageService.ParseSendRawData(message.RawData, message.Type);
|
||||
parsed.AppendLine("示例解析:");
|
||||
parsed.AppendLine($"充电指令:{sendDate.ChargeCommand}");
|
||||
parsed.AppendLine($"发送电压:{sendDate.SetVoltage}");
|
||||
parsed.AppendLine($"发送电流:{sendDate.SetCurrent}");
|
||||
parsed.AppendLine($"车辆ID:{sendDate.CurrentVehicleId}");
|
||||
parsed.AppendLine($"车辆电量:{sendDate.BatteryLevel}");
|
||||
parsed.AppendLine($"车辆电压:{sendDate.CarVoltage}");
|
||||
parsed.AppendLine($"车辆电流:{sendDate.CarCurrent}");
|
||||
|
||||
parsed.AppendLine($"充电指令:{sendData.ChargeCommand}");
|
||||
parsed.AppendLine($"发送电压:{sendData.SetVoltage}");
|
||||
parsed.AppendLine($"发送电流:{sendData.SetCurrent}");
|
||||
parsed.AppendLine($"车辆ID:{sendData.CurrentVehicleId}");
|
||||
parsed.AppendLine($"车辆电量:{sendData.BatteryLevel}");
|
||||
parsed.AppendLine($"车辆电压:{sendData.CarVoltage}");
|
||||
parsed.AppendLine($"车辆电流:{sendData.CarCurrent}");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
var recDate = messageService.ParseReceiveRawData(message.RawData, message.Type);
|
||||
string mechanismStatus = (int)recDate.MechanismStatus == 1 ? "伸出" : (int)recDate.MechanismStatus == 2 ? "缩回" : (int)recDate.MechanismStatus == 3 ? "运动中" : recDate.MechanismStatus.ToString();
|
||||
var recData = MessageService.ParseReceiveRawData(message.RawData, message.Type);
|
||||
string mechanismStatus = (int)recData.MechanismStatus == 1 ? "伸出"
|
||||
: (int)recData.MechanismStatus == 2 ? "缩回"
|
||||
: (int)recData.MechanismStatus == 3 ? "运动中"
|
||||
: recData.MechanismStatus.ToString();
|
||||
parsed.AppendLine("示例解析:");
|
||||
parsed.AppendLine($"机构状态:{mechanismStatus}");
|
||||
parsed.AppendLine($"实时电压:{recDate.RealTimeVoltage}");
|
||||
parsed.AppendLine($"实时电流:{recDate.RealTimeCurrent}");
|
||||
parsed.AppendLine($"充电量: {recDate.BatteryAH}");
|
||||
parsed.AppendLine($"是否报警:{recDate.HasAlarm}");
|
||||
parsed.AppendLine($"充电状态:{recDate.Status.ToString()}");
|
||||
|
||||
parsed.AppendLine($"实时电压:{recData.RealTimeVoltage}");
|
||||
parsed.AppendLine($"实时电流:{recData.RealTimeCurrent}");
|
||||
parsed.AppendLine($"充电量: {recData.BatteryAH}");
|
||||
parsed.AppendLine($"是否报警:{recData.HasAlarm}");
|
||||
parsed.AppendLine($"充电状态:{recData.Status}");
|
||||
}
|
||||
|
||||
|
||||
|
||||
txtParsedData.Text = parsed.ToString();
|
||||
return parsed.ToString();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
txtParsedData.Text = $"解析失败: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化十六进制字符串
|
||||
/// </summary>
|
||||
private string FormatHexString(string hexData)
|
||||
{
|
||||
if (string.IsNullOrEmpty(hexData))
|
||||
return string.Empty;
|
||||
|
||||
var formatted = new System.Text.StringBuilder();
|
||||
for (int i = 0; i < hexData.Length; i += 2)
|
||||
{
|
||||
if (i > 0 && i % 32 == 0)
|
||||
formatted.AppendLine();
|
||||
else if (i > 0)
|
||||
formatted.Append(" ");
|
||||
|
||||
if (i + 1 < hexData.Length)
|
||||
formatted.Append(hexData.Substring(i, 2));
|
||||
else
|
||||
formatted.Append(hexData[i]);
|
||||
}
|
||||
return formatted.ToString();
|
||||
}
|
||||
|
||||
// ==================== 事件处理 ====================
|
||||
|
||||
private void cmbIpFilter_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
LoadMessages();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"筛选改变失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void dgvMessages_SelectionChanged(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (dgvMessages.SelectedRows.Count > 0)
|
||||
{
|
||||
var row = dgvMessages.SelectedRows[0];
|
||||
var rawData = row.Cells[5].Value?.ToString();
|
||||
var ipAddress = row.Cells[2].Value?.ToString();
|
||||
var port = int.Parse(row.Cells[3].Value?.ToString() ?? "0");
|
||||
var timeStr = row.Cells[0].Value?.ToString();
|
||||
var directionStr = row.Cells[1].Value?.ToString();
|
||||
var stationId = row.Cells[6].Value?.ToString();
|
||||
var type = row.Cells[7].Value?.ToString();
|
||||
|
||||
// 构造消息对象用于解析
|
||||
var message = new CommunicationMessage
|
||||
{
|
||||
RawData = rawData,
|
||||
IpAddress = ipAddress,
|
||||
Port = port,
|
||||
Direction = directionStr == "发送" ? MessageDirection.Send : MessageDirection.Receive,
|
||||
StationId = stationId == "-" ? null : stationId,
|
||||
Length = rawData.Split(' ')?.Length ?? 0,
|
||||
Type=type,
|
||||
|
||||
};
|
||||
|
||||
if (DateTime.TryParse(timeStr, out DateTime timestamp))
|
||||
{
|
||||
message.Timestamp = timestamp;
|
||||
}
|
||||
|
||||
ParseMessage(message);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"选择报文失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void btnRefresh_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
RefreshIpFilter();
|
||||
LoadMessages();
|
||||
RequestStatisticsRefresh(dgvMessages?.Rows.Count ?? 0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"刷新失败: {ex.Message}", "错误",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void btnClear_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = MessageBox.Show(
|
||||
"确定要清空所有报文记录吗?",
|
||||
"确认清空",
|
||||
MessageBoxButtons.YesNo,
|
||||
MessageBoxIcon.Question);
|
||||
|
||||
if (result == DialogResult.Yes)
|
||||
{
|
||||
messageService.Clear();
|
||||
RefreshIpFilter();
|
||||
LoadMessages();
|
||||
if (txtParsedData != null)
|
||||
{
|
||||
txtParsedData.Clear();
|
||||
}
|
||||
dgvMessages.Rows.Clear();
|
||||
RequestStatisticsRefresh(0);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"清空报文失败: {ex.Message}", "错误",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void btnClose_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void CommunicationMonitorForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
// 取消订阅事件
|
||||
messageService.MessageAdded -= OnMessageAdded;
|
||||
uiFlushTimer.Stop();
|
||||
uiFlushTimer.Dispose();
|
||||
statsRefreshTimer.Stop();
|
||||
statsRefreshTimer.Dispose();
|
||||
}
|
||||
|
||||
private void button1_Click(object sender, EventArgs e)
|
||||
{
|
||||
isFormMessageStop = !isFormMessageStop;
|
||||
if (sender is Button pauseButton)
|
||||
{
|
||||
pauseButton.Text = isFormMessageStop ? "继续" : "暂停";
|
||||
return $"解析失败: {ex.Message}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="type.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
</root>
|
||||
@@ -5,7 +5,7 @@ using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using StandardScene.Utils;
|
||||
using CommonUsage;
|
||||
using LessokajiWeaverUtilities.Utilities;
|
||||
using Newtonsoft.Json;
|
||||
@@ -278,7 +278,7 @@ namespace StandardScene.Charge
|
||||
// 防止重复启动
|
||||
if (myStarted)
|
||||
{
|
||||
MessageBox.Show("充电进程已启动,不可重复启动");
|
||||
CycleUiHelper.Alert("提示", "充电进程已启动,不可重复启动");
|
||||
return;
|
||||
}
|
||||
status.status = "已启动";
|
||||
|
||||
Reference in New Issue
Block a user