Files
StandardSence/StandardScene.Core/Charge/ChargeStationManagementForm.cs
T
2026-06-14 11:19:15 +08:00

1390 lines
58 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using SimpleCore;
using System;
using System.Drawing;
using System.Linq;
using System.Net.NetworkInformation;
using System.Windows.Forms;
namespace StandardScene.Charge
{
/// <summary>
/// 充电桩管理窗口
/// </summary>
public partial class ChargeStationManagementForm : Form
{
private ChargeStationDataService dataService;
private ChargeStation selectedStation;
private System.Windows.Forms.Timer autoRefreshTimer;
private Ping Ping = new Ping();
private CommunicationMonitorForm communicationMonitorForm;
public ChargeStationManagementForm()
{
InitializeComponent();
dataService = ChargeStationDataService.Instance;
InitializeForm();
InitializeAutoRefresh();
}
/// <summary>
/// 初始化自动刷新定时器
/// </summary>
private void InitializeAutoRefresh()
{
autoRefreshTimer = new System.Windows.Forms.Timer();
autoRefreshTimer.Interval = 3000; // 每3秒刷新一次
autoRefreshTimer.Tick += AutoRefreshTimer_Tick;
autoRefreshTimer.Start();
}
/// <summary>
/// 自动刷新事件
/// </summary>
private void AutoRefreshTimer_Tick(object sender, EventArgs e)
{
// 保存当前选中的充电桩ID
string selectedStationId = null;
if (dgvStations.SelectedRows.Count > 0)
{
selectedStationId = dgvStations.SelectedRows[0].Cells[0].Value?.ToString();
}
// 刷新列表
LoadStations();
// 恢复选中状态
if (!string.IsNullOrEmpty(selectedStationId))
{
foreach (DataGridViewRow row in dgvStations.Rows)
{
if (row.Cells[0].Value?.ToString() == selectedStationId)
{
row.Selected = true;
dgvStations.CurrentCell = row.Cells[0];
break;
}
}
}
}
/// <summary>
/// 窗体关闭时停止定时器
/// </summary>
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (autoRefreshTimer != null)
{
autoRefreshTimer.Stop();
autoRefreshTimer.Dispose();
}
base.OnFormClosing(e);
}
private void InitializeForm()
{
// 设置窗口属性
this.Text = "充电桩管理系统";
this.Size = new Size(1200, 700);
this.StartPosition = FormStartPosition.CenterScreen;
this.MinimumSize = new Size(1000, 600);
// 设置表头文字垂直排列
SetupVerticalHeaderText();
// 初始化状态筛选下拉框
InitializeStatusFilter();
// 加载数据
LoadStations();
// 设置默认状态为新增模式
ClearEditFields();
}
/// <summary>
/// 设置表头文字垂直排列
/// </summary>
private void SetupVerticalHeaderText()
{
if (dgvStations == null)
return;
// 增加列标题高度以容纳垂直文字
dgvStations.ColumnHeadersHeight = 100;
// 订阅列标题绘制事件
dgvStations.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
dgvStations.CellPainting += DgvStations_CellPainting;
// 固定行高度
dgvStations.RowTemplate.Height = 35;
dgvStations.AllowUserToResizeRows = false;
dgvStations.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing;
dgvStations.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;
}
/// <summary>
/// 自定义绘制列标题(垂直文字)
/// </summary>
private void DgvStations_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
// 只处理列标题行
if (e.RowIndex == -1 && e.ColumnIndex >= 0)
{
try
{
// 绘制背景
e.PaintBackground(e.CellBounds, true);
// 获取列标题文本
string headerText = dgvStations.Columns[e.ColumnIndex].HeaderText;
// 设置文字格式(垂直排列,从上到下)
using (var brush = new SolidBrush(dgvStations.ColumnHeadersDefaultCellStyle.ForeColor))
using (var format = new StringFormat())
{
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Near;
format.FormatFlags = StringFormatFlags.DirectionVertical; // 垂直文字
// 计算绘制位置(居中)
float x = e.CellBounds.Left + (e.CellBounds.Width - e.Graphics.MeasureString("测", dgvStations.ColumnHeadersDefaultCellStyle.Font).Width) / 2;
float y = e.CellBounds.Top + 5;
// 绘制垂直文字
e.Graphics.DrawString(
headerText,
dgvStations.ColumnHeadersDefaultCellStyle.Font,
brush,
new RectangleF(x, y, e.CellBounds.Width, e.CellBounds.Height - 10),
format);
}
// 绘制边框
e.Paint(e.CellBounds, DataGridViewPaintParts.Border);
// 标记为已处理
e.Handled = true;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"绘制列标题失败: {ex.Message}");
}
}
}
/// <summary>
/// 初始化状态筛选下拉框
/// </summary>
private void InitializeStatusFilter()
{
if (cmbStatusFilter != null)
{
cmbStatusFilter.Items.Clear();
cmbStatusFilter.Items.Add("全部状态");
cmbStatusFilter.Items.Add("空闲");
cmbStatusFilter.Items.Add("充电中");
cmbStatusFilter.Items.Add("故障");
cmbStatusFilter.Items.Add("离线");
cmbStatusFilter.SelectedIndex = 0; // 默认显示全部
}
}
/// <summary>
/// 加载充电桩列表
/// </summary>
private void LoadStations()
{
try
{
var stations = dataService.GetAllStations();
// 根据状态筛选
if (cmbStatusFilter != null && cmbStatusFilter.SelectedIndex > 0)
{
var filterStatus = GetStatusFromFilterIndex(cmbStatusFilter.SelectedIndex);
stations = stations.Where(s => s.Status == filterStatus).ToList();
}
dgvStations.Rows.Clear();
foreach (var station in stations)
{
try
{
if (Ping.Send(station.IpAddress, 1000).Status == IPStatus.Success)
{
station.CommStatus = CommunicationStatus.Normal;
}
else
{
station.CommStatus = CommunicationStatus.Error;
}
}
catch (Exception)
{
station.CommStatus = CommunicationStatus.Error;
}
var index = dgvStations.Rows.Add(
station.StationId,
station.Name,
GetTypeText(station.Type),
GetChargeMethodText(station.ChargeMethod),
//station.IpAddress,
//station.Port,
station.SiteId?.ToString() ?? "",
FormatTimeToMinuteSecond(station.LastSendTime),
FormatTimeToMinuteSecond(station.LastReceiveTime),
FormatCommStatusDisplay(station.CommStatus),
FormatChargeCommandStatusDisplay(station.ChargeCommandStatus),
FormatMechanismStatusDisplay(station.MechanismStatus),
string.IsNullOrWhiteSpace(station.CurrentVehicle) ? "-" : station.CurrentVehicle,
station.BatteryLevel > 0 ? $"{station.BatteryLevel:F1}%" : "-",
FormatAlarmDisplay(station),
//station.SetVoltage,
//station.SetElectricCurrent,
station.RealTimeVoltage.ToString("F1"),
station.RealTimeCurrent.ToString("F1"),
GetStatusText(station.Status),
station.Enabled ? "是" : "否",
station.Remarks
);
// 根据状态设置行颜色(扁平化设计)
var row = dgvStations.Rows[index];
// 通讯状态列样式设置(第9列,因为增加了充电方式列)
var commCell = row.Cells[9];
switch (station.CommStatus)
{
case CommunicationStatus.Normal:
commCell.Style.ForeColor = Color.FromArgb(76, 175, 80); // 绿色
// commCell.Style.Font = new Font(commCell.Style.Font ?? row.DefaultCellStyle.Font, FontStyle.Bold);
break;
case CommunicationStatus.Delayed:
commCell.Style.ForeColor = Color.FromArgb(255, 152, 0); // 橙色
// commCell.Style.Font = new Font(commCell.Style.Font ?? row.DefaultCellStyle.Font, FontStyle.Bold);
break;
case CommunicationStatus.Timeout:
case CommunicationStatus.Disconnected:
case CommunicationStatus.Error:
commCell.Style.ForeColor = Color.FromArgb(244, 67, 54); // 红色
// commCell.Style.Font = new Font(commCell.Style.Font ?? row.DefaultCellStyle.Font, FontStyle.Bold);
break;
case CommunicationStatus.Unknown:
commCell.Style.ForeColor = Color.FromArgb(158, 158, 158); // 灰色
break;
}
// 充电指令状态列样式设置(第10列)
var chargeCommandCell = row.Cells[10];
switch (station.ChargeCommandStatus)
{
case ChargeCommandStatus.Stopped:
chargeCommandCell.Style.ForeColor = Color.FromArgb(158, 158, 158); // 灰色
break;
case ChargeCommandStatus.Started:
chargeCommandCell.Style.ForeColor = Color.FromArgb(76, 175, 80); // 绿色
// chargeCommandCell.Style.Font = new Font(chargeCommandCell.Style.Font ?? row.DefaultCellStyle.Font, FontStyle.Bold);
break;
}
// 机构状态列样式设置(第11列)
var mechanismCell = row.Cells[11];
switch (station.MechanismStatus)
{
case MechanismStatus.Retracted:
mechanismCell.Style.ForeColor = Color.FromArgb(76, 175, 80); // 绿色
//mechanismCell.Style.Font = new Font(mechanismCell.Style.Font ?? row.DefaultCellStyle.Font, FontStyle.Bold);
break;
case MechanismStatus.Extending:
mechanismCell.Style.ForeColor = Color.FromArgb(33, 150, 243); // 蓝色
//mechanismCell.Style.Font = new Font(mechanismCell.Style.Font ?? row.DefaultCellStyle.Font, FontStyle.Bold);
break;
case MechanismStatus.Extended:
mechanismCell.Style.ForeColor = Color.FromArgb(255, 0, 0); //
//mechanismCell.Style.Font = new Font(mechanismCell.Style.Font ?? row.DefaultCellStyle.Font, FontStyle.Bold);
break;
break;
}
// 电量列样式设置(第13列)
if (station.BatteryLevel > 0)
{
var batteryCell = row.Cells[13];
if (station.BatteryLevel >= 80)
{
batteryCell.Style.ForeColor = Color.FromArgb(76, 175, 80); // 绿色 - 电量充足
//batteryCell.Style.Font = new Font(batteryCell.Style.Font ?? row.DefaultCellStyle.Font, FontStyle.Bold);
}
else if (station.BatteryLevel >= 50)
{
batteryCell.Style.ForeColor = Color.FromArgb(33, 150, 243); // 蓝色 - 电量中等
//batteryCell.Style.Font = new Font(batteryCell.Style.Font ?? row.DefaultCellStyle.Font, FontStyle.Bold);
}
else if (station.BatteryLevel >= 20)
{
batteryCell.Style.ForeColor = Color.FromArgb(255, 152, 0); // 橙色 - 电量偏低
//batteryCell.Style.Font = new Font(batteryCell.Style.Font ?? row.DefaultCellStyle.Font, FontStyle.Bold);
}
else
{
batteryCell.Style.ForeColor = Color.FromArgb(244, 67, 54); // 红色 - 电量低
//batteryCell.Style.Font = new Font(batteryCell.Style.Font ?? row.DefaultCellStyle.Font, FontStyle.Bold);
}
}
// 如果有报警,整行显示红色
if (station.HasAlarm)
{
row.DefaultCellStyle.BackColor = Color.FromArgb(255, 205, 210); // 浅红色背景 #FFCDD2
row.DefaultCellStyle.ForeColor = Color.FromArgb(198, 40, 40); // 深红色文字
var baseFont = row.DefaultCellStyle.Font ?? dgvStations.DefaultCellStyle.Font ?? new Font("微软雅黑", 9F);
row.DefaultCellStyle.Font = new Font(baseFont, FontStyle.Bold);
}
else
{
// 根据状态设置颜色
switch (station.Status)
{
case ChargeStationStatus.Idle:
row.DefaultCellStyle.BackColor = Color.FromArgb(232, 245, 233); // 浅绿色 #E8F5E9
row.DefaultCellStyle.ForeColor = Color.FromArgb(46, 125, 50); // 深绿色文字
break;
case ChargeStationStatus.Charging:
row.DefaultCellStyle.BackColor = Color.FromArgb(200, 230, 201); // 亮绿色 #C8E6C9
row.DefaultCellStyle.ForeColor = Color.FromArgb(27, 94, 32); // 深绿色文字
break;
case ChargeStationStatus.Fault:
row.DefaultCellStyle.BackColor = Color.FromArgb(255, 205, 210); // 浅红色 #FFCDD2
row.DefaultCellStyle.ForeColor = Color.FromArgb(198, 40, 40); // 深红色文字
break;
case ChargeStationStatus.Battery:
row.DefaultCellStyle.BackColor = Color.FromArgb(238, 238, 238); // 浅灰色 #EEEEEE
row.DefaultCellStyle.ForeColor = Color.FromArgb(97, 97, 97); // 深灰色文字
break;
}
}
}
// 更新统计信息
UpdateStatistics();
// 更新标题显示筛选状态
UpdateTitleWithFilter(stations.Count);
}
catch (Exception ex)
{
MessageBox.Show($"加载数据失败: {ex.Message}\n\n堆栈:\n{ex.StackTrace}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 根据筛选器索引获取状态
/// </summary>
private ChargeStationStatus GetStatusFromFilterIndex(int index)
{
switch (index)
{
case 1: return ChargeStationStatus.Idle; // 空闲
case 2: return ChargeStationStatus.Charging; // 充电中
case 3: return ChargeStationStatus.Fault; // 故障
case 4: return ChargeStationStatus.Battery; // 离线
default: return ChargeStationStatus.Idle;
}
}
/// <summary>
/// 更新标题显示筛选信息
/// </summary>
private void UpdateTitleWithFilter(int displayCount)
{
var totalCount = dataService.GetAllStations().Count;
if (cmbStatusFilter != null && cmbStatusFilter.SelectedIndex > 0)
{
this.Text = $"充电桩管理系统 - 显示: {displayCount}/{totalCount} ({cmbStatusFilter.Text})";
}
else
{
this.Text = $"充电桩管理系统 - 总数: {totalCount}";
}
}
/// <summary>
/// 更新统计信息
/// </summary>
private void UpdateStatistics()
{
var stations = dataService.GetAllStations();
var total = stations.Count;
var idle = stations.Count(s => s.Status == ChargeStationStatus.Idle);
var charging = stations.Count(s => s.Status == ChargeStationStatus.Charging);
var fault = stations.Count(s => s.Status == ChargeStationStatus.Fault);
var offline = stations.Count(s => s.Status == ChargeStationStatus.Battery);
lblStatistics.Text = $"总数: {total} | 空闲: {idle} | 充电中: {charging} | 故障: {fault} | AGV电池已接入: {offline}";
}
/// <summary>
/// 获取状态文本
/// </summary>
private string GetStatusText(ChargeStationStatus status)
{
switch (status)
{
case ChargeStationStatus.Idle: return "空闲";
case ChargeStationStatus.Charging: return "充电中";
case ChargeStationStatus.Fault: return "故障";
case ChargeStationStatus.Battery: return "AGV电池已接入";
default: return "未知";
}
}
/// <summary>
/// 格式化时间为 mm:ss 格式
/// </summary>
private string FormatTimeToMinuteSecond(DateTime? dateTime)
{
if (dateTime == null)
{
return "--:--";
}
return dateTime.Value.ToString("mm:ss");
}
/// <summary>
/// 格式化机构伸缩状态显示
/// </summary>
private string FormatMechanismStatusDisplay(MechanismStatus status)
{
switch (status)
{
case MechanismStatus.Extended:
return "◆ 伸出";
case MechanismStatus.Retracted:
return "◇ 缩回";
case MechanismStatus.Extending:
return "▶ 运动中";
default:
return "? 未知";
}
}
/// <summary>
/// 格式化充电指令状态显示
/// </summary>
private string FormatChargeCommandStatusDisplay(ChargeCommandStatus status)
{
switch (status)
{
case ChargeCommandStatus.Stopped:
return "◯ 停止";
case ChargeCommandStatus.Started:
return "▶ 启动";
default:
return "◯ 停止";
}
}
/// <summary>
/// 格式化通讯状态显示
/// </summary>
private string FormatCommStatusDisplay(CommunicationStatus status)
{
switch (status)
{
case CommunicationStatus.Normal:
return "✓ 正常";
case CommunicationStatus.Delayed:
return "⚠ 延迟";
case CommunicationStatus.Timeout:
return "✗ 超时";
case CommunicationStatus.Disconnected:
return "✗ 断开";
case CommunicationStatus.Error:
return "✗ 错误";
case CommunicationStatus.Unknown:
default:
return "? 未知";
}
}
/// <summary>
/// 格式化报警信息显示
/// </summary>
private string FormatAlarmDisplay(ChargeStation station)
{
if (!station.HasAlarm)
{
return "正常";
}
string levelText = GetAlarmLevelText(station.AlarmLevel);
if (string.IsNullOrWhiteSpace(station.AlarmMessage))
{
return $"【{levelText}】";
}
return $"{station.AlarmMessage}";
}
/// <summary>
/// 获取报警级别文本
/// </summary>
private string GetAlarmLevelText(AlarmLevel level)
{
switch (level)
{
case AlarmLevel.None: return "无";
case AlarmLevel.Low: return "低";
case AlarmLevel.Medium: return "中";
case AlarmLevel.High: return "高";
case AlarmLevel.Critical: return "严重";
default: return "未知";
}
}
/// <summary>
/// 获取类型文本
/// </summary>
private string GetTypeText(ChargeStationType type)
{
switch (type)
{
case ChargeStationType.FRLDTall: return "FRLD高款充电桩";
case ChargeStationType.FRLDShort: return "FRLD矮款充电桩";
case ChargeStationType.MuXing: return "牧星充电桩";
default: return "未知";
}
}
/// <summary>
/// 获取充电方式文本
/// </summary>
private string GetChargeMethodText(ChargeMethodType method)
{
switch (method)
{
case ChargeMethodType.Ground: return "地充";
case ChargeMethodType.Rear: return "尾充";
case ChargeMethodType.Side: return "侧充";
default: return "未知";
}
}
/// <summary>
/// 设置编辑模式
/// </summary>
/// <summary>
/// 清空编辑区
/// </summary>
private void ClearEditFields()
{
selectedStation = null;
txtStationId.Text = ""; // 手动输入编号
txtName.Text = "";
cmbType.SelectedIndex = 1;
cmbChargeMethod.SelectedIndex = 0; // 默认地充
chargeCarType.SelectedIndex = 0;
// 触发充电方式改变事件,更新"屏蔽机构状态交互"的可见性
cmbChargeMethod_SelectedIndexChanged(null, null);
txtIpAddress.Text = "192.168.";
numPort.Value = 2000;
numVoltage.Value = 48;
numCurrent.Value = 32;
chkEnabled.Checked = true;
chkShieldSiteMechanismStatus.Checked = false;
numSiteId.Value = 0;
txtRemarks.Text = "";
// 清空实时状态显示
ClearRealTimeInfo();
// 新增模式:所有字段可编辑
SetEditMode(true);
btnSave.Text = "保存";
btnDelete.Enabled = false;
}
/// <summary>
/// 清空实时状态显示区域
/// </summary>
private void ClearRealTimeInfo()
{
lblCurrentVehicleValue.Text = "-";
lblCurrentVehicleValue.ForeColor = Color.Gray;
lblBatteryLevelValue.Text = "-";
lblBatteryLevelValue.ForeColor = Color.Gray;
lblRealTimeVoltageValue.Text = "0.0 V";
lblRealTimeVoltageValue.ForeColor = Color.Gray;
lblRealTimeCurrentValue.Text = "0.0 A";
lblRealTimeCurrentValue.ForeColor = Color.Gray;
lblCommStatusValue.Text = "? 未知";
lblCommStatusValue.ForeColor = Color.Gray;
lblChargeCommandStatusValue.Text = "◯ 停止";
lblChargeCommandStatusValue.ForeColor = Color.Gray;
lblMechanismStatusValue.Text = "? 未知";
lblMechanismStatusValue.ForeColor = Color.Gray;
lblAlarmValue.Text = "-";
lblAlarmValue.ForeColor = Color.Gray;
}
/// <summary>
/// 设置编辑模式
/// </summary>
/// <param name="editable">true=可编辑,false=只读</param>
private void SetEditMode(bool editable, bool isList = false)
{
// 编号在新增时可编辑,编辑时只读
if (selectedStation == null)
{
// 新增模式:编号可编辑
txtStationId.ReadOnly = false;
txtStationId.BackColor = Color.White;
}
else
{
// 编辑模式:编号只读
txtStationId.ReadOnly = true;
txtStationId.BackColor = Color.LightGray;
}
// 其他字段根据参数设置
txtName.ReadOnly = !editable;
cmbType.Enabled = isList ? false : editable;
cmbChargeMethod.Enabled = editable;
txtIpAddress.ReadOnly = !editable;
numPort.ReadOnly = !editable;
numVoltage.ReadOnly = !editable;
numCurrent.ReadOnly = !editable;
chkEnabled.Enabled = editable;
chkShieldSiteMechanismStatus.Enabled = editable;
numSiteId.ReadOnly = !editable;
txtRemarks.ReadOnly = !editable;
// 设置背景颜色
if (!editable)
{
txtName.BackColor = Color.WhiteSmoke;
txtIpAddress.BackColor = Color.WhiteSmoke;
txtRemarks.BackColor = Color.WhiteSmoke;
}
else
{
txtName.BackColor = Color.White;
txtIpAddress.BackColor = Color.White;
txtRemarks.BackColor = Color.White;
}
// 控制按钮状态
btnSave.Enabled = editable;
}
/// <summary>
/// 从编辑区创建充电桩对象
/// </summary>
private ChargeStation CreateStationFromFields()
{
//var station = selectedStation ?? new ChargeStation();
var station = new ChargeStation();
station.StationId = txtStationId.Text.Trim();
station.Name = txtName.Text.Trim();
station.Type = (ChargeStationType)cmbType.SelectedIndex;
station.ChargeMethod = (ChargeMethodType)cmbChargeMethod.SelectedIndex;
station.IpAddress = txtIpAddress.Text.Trim();
station.Port = (int)numPort.Value;
station.SetVoltage = (double)numVoltage.Value;
station.SetElectricCurrent = (double)numCurrent.Value;
station.Enabled = chkEnabled.Checked;
station.ShieldSiteMechanismStatus = chkShieldSiteMechanismStatus.Checked;
station.GroupCarType = (ChargeStationCarType)chargeCarType.SelectedIndex;
station.SiteId = numSiteId.Value > 0 ? (int?)numSiteId.Value : null;
station.Remarks = txtRemarks.Text.Trim();
return station;
}
/// <summary>
/// 加载充电桩到编辑区
/// </summary>
private void LoadStationToFields(ChargeStation station)
{
selectedStation = station;
// 加载基本信息(可编辑部分)
txtStationId.Text = station.StationId;
txtName.Text = station.Name;
cmbType.SelectedIndex = (int)station.Type;
cmbChargeMethod.SelectedIndex = (int)station.ChargeMethod;
// 触发充电方式改变事件,更新"屏蔽机构状态交互"的可见性
cmbChargeMethod_SelectedIndexChanged(null, null);
txtIpAddress.Text = station.IpAddress;
numPort.Value = station.Port;
numVoltage.Value = (decimal)station.SetVoltage;
numCurrent.Value = (decimal)station.SetElectricCurrent;
chkEnabled.Checked = station.Enabled;
chkShieldSiteMechanismStatus.Checked = station.ShieldSiteMechanismStatus;
chargeCarType.SelectedIndex = (int)station.GroupCarType;
numSiteId.Value = station.SiteId ?? 0;
txtRemarks.Text = station.Remarks ?? "";
// 加载实时状态信息(只读部分)
LoadRealTimeInfo(station);
// 查看模式:所有字段只读
SetEditMode(false);
btnSave.Text = "修改";
btnDelete.Enabled = true;
}
/// <summary>
/// 加载实时状态信息到显示区域
/// </summary>
private void LoadRealTimeInfo(ChargeStation station)
{
// 当前车辆
lblCurrentVehicleValue.Text = string.IsNullOrWhiteSpace(station.CurrentVehicle) ? "-" : station.CurrentVehicle;
// 电量
if (station.BatteryLevel > 0)
{
lblBatteryLevelValue.Text = $"{station.BatteryLevel:F1}%";
if (station.BatteryLevel >= 80)
{
lblBatteryLevelValue.ForeColor = Color.FromArgb(76, 175, 80); // 绿色
}
else if (station.BatteryLevel >= 50)
{
lblBatteryLevelValue.ForeColor = Color.FromArgb(33, 150, 243); // 蓝色
}
else if (station.BatteryLevel >= 20)
{
lblBatteryLevelValue.ForeColor = Color.FromArgb(255, 152, 0); // 橙色
}
else
{
lblBatteryLevelValue.ForeColor = Color.FromArgb(244, 67, 54); // 红色
}
}
else
{
lblBatteryLevelValue.Text = "-";
lblBatteryLevelValue.ForeColor = Color.Gray;
}
// 实时电压
lblRealTimeVoltageValue.Text = $"{station.RealTimeVoltage:F1} V";
lblRealTimeVoltageValue.ForeColor = station.RealTimeVoltage > 0
? Color.FromArgb(33, 150, 243) // 蓝色
: Color.Gray;
// 实时电流
lblRealTimeCurrentValue.Text = $"{station.RealTimeCurrent:F1} A";
lblRealTimeCurrentValue.ForeColor = station.RealTimeCurrent > 0
? Color.FromArgb(33, 150, 243) // 蓝色
: Color.Gray;
// 通讯状态
lblCommStatusValue.Text = FormatCommStatusDisplay(station.CommStatus);
switch (station.CommStatus)
{
case CommunicationStatus.Normal:
lblCommStatusValue.ForeColor = Color.FromArgb(76, 175, 80); // 绿色
break;
case CommunicationStatus.Delayed:
lblCommStatusValue.ForeColor = Color.FromArgb(255, 193, 7); // 黄色
break;
case CommunicationStatus.Timeout:
case CommunicationStatus.Disconnected:
case CommunicationStatus.Error:
lblCommStatusValue.ForeColor = Color.FromArgb(244, 67, 54); // 红色
break;
default:
lblCommStatusValue.ForeColor = Color.Gray;
break;
}
// 充电指令状态
lblChargeCommandStatusValue.Text = FormatChargeCommandStatusDisplay(station.ChargeCommandStatus);
lblChargeCommandStatusValue.ForeColor = station.ChargeCommandStatus == ChargeCommandStatus.Started
? Color.FromArgb(76, 175, 80) // 绿色
: Color.Gray;
// 机构状态
lblMechanismStatusValue.Text = FormatMechanismStatusDisplay(station.MechanismStatus);
switch (station.MechanismStatus)
{
case MechanismStatus.Retracted:
lblMechanismStatusValue.ForeColor = Color.FromArgb(76, 175, 80); // 绿色
break;
case MechanismStatus.Extending:
lblMechanismStatusValue.ForeColor = Color.FromArgb(33, 150, 243); // 蓝色
break;
case MechanismStatus.Extended:
lblMechanismStatusValue.ForeColor = Color.FromArgb(255, 0, 0); // 蓝色
break;
default:
lblMechanismStatusValue.ForeColor = Color.Gray;
break;
}
// 报警信息
if (station.HasAlarm)
{
string levelText = "";
switch (station.AlarmLevel)
{
case AlarmLevel.Critical:
levelText = "严重";
lblAlarmValue.ForeColor = Color.FromArgb(183, 28, 28); // 深红色
break;
case AlarmLevel.High:
levelText = "高";
lblAlarmValue.ForeColor = Color.FromArgb(244, 67, 54); // 红色
break;
case AlarmLevel.Medium:
levelText = "中";
lblAlarmValue.ForeColor = Color.FromArgb(255, 152, 0); // 橙色
break;
case AlarmLevel.Low:
levelText = "低";
lblAlarmValue.ForeColor = Color.FromArgb(255, 193, 7); // 黄色
break;
default:
levelText = "未知";
lblAlarmValue.ForeColor = Color.Gray;
break;
}
lblAlarmValue.Text = $"【{levelText}】{station.AlarmMessage}";
}
else
{
lblAlarmValue.Text = "正常";
lblAlarmValue.ForeColor = Color.FromArgb(76, 175, 80); // 绿色
}
}
// ==================== 事件处理 ====================
/// <summary>
/// 充电方式改变事件 - 控制"屏蔽机构状态交互"选项的显示
/// </summary>
private void cmbChargeMethod_SelectedIndexChanged(object sender, EventArgs e)
{
// 只有侧充(Side=2)时才显示"屏蔽机构状态交互"选项
bool isSideCharge = cmbChargeMethod.SelectedIndex == (int)ChargeMethodType.Side;
chkShieldSiteMechanismStatus.Visible = isSideCharge;
// 如果不是侧充,自动取消勾选
if (!isSideCharge)
{
chkShieldSiteMechanismStatus.Checked = false;
}
}
private void btnSave_Click(object sender, EventArgs e)
{
try
{
// 如果当前是只读模式(查看模式),点击"修改"按钮切换到编辑模式
if (btnSave.Text == "修改")
{
SetEditMode(true);
btnSave.Text = "保存";
return;
}
// 以下是保存逻辑
// 充电桩编号验证:1-99之间的数字
string stationId = txtStationId.Text.Trim();
if (string.IsNullOrEmpty(stationId))
{
MessageBox.Show("请输入充电桩编号(1-99", "验证失败",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtStationId.Focus();
return;
}
// 验证是否为数字且在1-99范围内
if (!int.TryParse(stationId, out int stationNumber) || stationNumber < 1 || stationNumber > 99)
{
MessageBox.Show("充电桩编号必须是1-99之间的数字", "验证失败",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtStationId.Focus();
return;
}
// 检查编号是否重复(新增时)
if (selectedStation == null)
{
var existingStations = dataService.GetAllStations();
if (existingStations.Any(s => s.StationId == stationId))
{
MessageBox.Show($"充电桩编号 {stationId} 已存在,请输入其他编号", "验证失败",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtStationId.Focus();
return;
}
}
var Site = SimpleLib.GetSite((int)numSiteId.Value);
if (Site == null) //判断站点是否在S里。
{
MessageBox.Show($"站点ID{numSiteId.Value} 未在调度系统上", "验证失败",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
numSiteId.Focus();
return;
}
var station = CreateStationFromFields();
string errorMessage;
bool success;
if (selectedStation == null)
{
// 新增
success = dataService.AddStation(station, out errorMessage);
}
else
{
// 更新
success = dataService.UpdateStation(station, out errorMessage, true);
}
if (success)
{
Site.name = station.Name;
//Site.fields["chargeNum"] = station.StationId;
//Site.fields["stationIP"] = station.IpAddress;
//Site.fields["stationPort"] = station.Port.ToString();
//switch (station.Type)
//{
// case ChargeStationType.FRLDTall:
// Site.fields["Charge"] = "FLChargeStation";
// break;
// case ChargeStationType.FRLDShort:
// Site.fields["Charge"] = "PCBChargeStation";
// Site.fields["CommunicationType"] = "UDP";
// break;
// case ChargeStationType.MuXing:
// Site.fields["Charge"] = "MuXingChargeStation";
// break;
// default:
// break;
//}
Site.fields["setVoltage"] = station.SetVoltage.ToString();
Site.fields["setElectricCurrent"] = station.SetElectricCurrent.ToString();
if (!station.Enabled)
{
Site.fields["group"] = "禁用";
}
else
{
Site.fields["group"] = station.GroupCarType.ToString();
}
LoadStations();
ClearEditFields();
MessageBox.Show("保存成功", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
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 (dgvStations.SelectedRows.Count == 0)
{
MessageBox.Show("请先选择要删除的充电桩", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
var stationId = dgvStations.SelectedRows[0].Cells[0].Value.ToString();
var stationName = dgvStations.SelectedRows[0].Cells[1].Value.ToString();
var result = MessageBox.Show(
$"确定要删除充电桩 [{stationId}] {stationName} 吗?",
"确认删除",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
if (dataService.DeleteStation(stationId, out string errorMessage))
{
var Site = SimpleLib.GetSite((int)numSiteId.Value);
if (Site != null) //判断站点是否在S里。
{
Site.name = "NoName";
Site.fields.Remove("setVoltage");
Site.fields.Remove("setElectricCurrent");
Site.fields.Remove("Charge");
Site.fields.Remove("group");
}
MessageBox.Show("删除成功!", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Information);
LoadStations();
ClearEditFields();
}
else
{
MessageBox.Show($"删除失败: {errorMessage}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
// 如果有选中的充电桩,恢复到只读模式
//if (selectedStation != null)
//{
// LoadStationToFields(selectedStation);
//}
//else
{
// 否则清空为新增模式
ClearEditFields();
}
}
private void btnRefresh_Click(object sender, EventArgs e)
{
dataService.Reload();
LoadStations();
MessageBox.Show("刷新成功!", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void dgvStations_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0)
{
var stationId = dgvStations.Rows[e.RowIndex].Cells[0].Value.ToString();
var station = dataService.GetStationById(stationId);
if (station != null)
{
LoadStationToFields(station);
SetEditMode(true, true);
}
}
}
private void txtSearch_TextChanged(object sender, EventArgs e)
{
ApplyFilters();
}
private void cmbStatusFilter_SelectedIndexChanged(object sender, EventArgs e)
{
ApplyFilters();
}
/// <summary>
/// 应用搜索和状态筛选
/// </summary>
private void ApplyFilters()
{
var stations = dataService.GetAllStations();
// 应用搜索筛选
var searchText = txtSearch.Text.Trim().ToLower();
if (!string.IsNullOrEmpty(searchText))
{
stations = stations
.Where(s => s.StationId.ToLower().Contains(searchText) ||
s.Name.ToLower().Contains(searchText) ||
s.IpAddress.Contains(searchText) ||
GetTypeText(s.Type).Contains(searchText))
.ToList();
}
// 应用状态筛选
if (cmbStatusFilter != null && cmbStatusFilter.SelectedIndex > 0)
{
var filterStatus = GetStatusFromFilterIndex(cmbStatusFilter.SelectedIndex);
stations = stations.Where(s => s.Status == filterStatus).ToList();
}
// 显示结果
dgvStations.Rows.Clear();
foreach (var station in stations)
{
var index = dgvStations.Rows.Add(
station.StationId,
station.Name,
GetTypeText(station.Type),
GetChargeMethodText(station.ChargeMethod),
//station.IpAddress,
//station.Port,
station.SiteId?.ToString() ?? "",
FormatTimeToMinuteSecond(station.LastSendTime),
FormatTimeToMinuteSecond(station.LastReceiveTime),
FormatCommStatusDisplay(station.CommStatus),
FormatChargeCommandStatusDisplay(station.ChargeCommandStatus),
FormatMechanismStatusDisplay(station.MechanismStatus),
string.IsNullOrWhiteSpace(station.CurrentVehicle) ? "-" : station.CurrentVehicle,
station.BatteryLevel > 0 ? $"{station.BatteryLevel:F1}%" : "-",
FormatAlarmDisplay(station),
//station.SetVoltage,
//station.SetElectricCurrent,
station.RealTimeVoltage.ToString("F1"),
station.RealTimeCurrent.ToString("F1"),
GetStatusText(station.Status),
station.Enabled ? "是" : "否",
station.Remarks
);
// 根据状态设置行颜色(扁平化设计)
var row = dgvStations.Rows[index];
// 通讯状态列样式设置(第9列)
var commCell = row.Cells[9];
switch (station.CommStatus)
{
case CommunicationStatus.Normal:
commCell.Style.ForeColor = Color.FromArgb(76, 175, 80); // 绿色
// commCell.Style.Font = new Font(commCell.Style.Font ?? row.DefaultCellStyle.Font, FontStyle.Bold);
break;
case CommunicationStatus.Delayed:
commCell.Style.ForeColor = Color.FromArgb(255, 152, 0); // 橙色
// commCell.Style.Font = new Font(commCell.Style.Font ?? row.DefaultCellStyle.Font, FontStyle.Bold);
break;
case CommunicationStatus.Timeout:
case CommunicationStatus.Disconnected:
commCell.Style.ForeColor = Color.FromArgb(244, 67, 54); // 红色
// commCell.Style.Font = new Font(commCell.Style.Font ?? row.DefaultCellStyle.Font, FontStyle.Bold);
break;
case CommunicationStatus.Unknown:
commCell.Style.ForeColor = Color.FromArgb(158, 158, 158); // 灰色
break;
}
// 充电指令状态列样式设置(第10列)
var chargeCommandCell = row.Cells[10];
switch (station.ChargeCommandStatus)
{
case ChargeCommandStatus.Stopped:
chargeCommandCell.Style.ForeColor = Color.FromArgb(158, 158, 158); // 灰色
break;
case ChargeCommandStatus.Started:
chargeCommandCell.Style.ForeColor = Color.FromArgb(76, 175, 80); // 绿色
//chargeCommandCell.Style.Font = new Font(chargeCommandCell.Style.Font ?? row.DefaultCellStyle.Font, FontStyle.Bold);
break;
}
// 机构状态列样式设置(第11列)
var mechanismCell = row.Cells[11];
switch (station.MechanismStatus)
{
case MechanismStatus.Retracted:
mechanismCell.Style.ForeColor = Color.FromArgb(76, 175, 80); // 绿色
// mechanismCell.Style.Font = new Font(mechanismCell.Style.Font ?? mechanismCell.Style.Font, FontStyle.Bold);
break;
case MechanismStatus.Extending:
mechanismCell.Style.ForeColor = Color.FromArgb(33, 150, 243); // 蓝色
// mechanismCell.Style.Font = new Font(mechanismCell.Style.Font ?? row.DefaultCellStyle.Font, FontStyle.Bold);
break;
}
// 电量列样式设置(第13列)
if (station.BatteryLevel > 0)
{
var batteryCell = row.Cells[13];
if (station.BatteryLevel >= 80)
{
batteryCell.Style.ForeColor = Color.FromArgb(76, 175, 80); // 绿色 - 电量充足
//batteryCell.Style.Font = new Font(batteryCell.Style.Font ?? batteryCell.Style.Font, FontStyle.Bold);
}
else if (station.BatteryLevel >= 50)
{
batteryCell.Style.ForeColor = Color.FromArgb(33, 150, 243); // 蓝色 - 电量中等
//batteryCell.Style.Font = new Font(batteryCell.Style.Font ?? batteryCell.Style.Font, FontStyle.Bold);
}
else if (station.BatteryLevel >= 20)
{
batteryCell.Style.ForeColor = Color.FromArgb(255, 152, 0); // 橙色 - 电量偏低
//batteryCell.Style.Font = new Font(batteryCell.Style.Font ?? batteryCell.Style.Font, FontStyle.Bold);
}
else
{
batteryCell.Style.ForeColor = Color.FromArgb(244, 67, 54); // 红色 - 电量低
//batteryCell.Style.Font = new Font(batteryCell.Style.Font ?? batteryCell.Style.Font, FontStyle.Bold);
}
}
// 如果有报警,整行显示红色
if (station.HasAlarm)
{
row.DefaultCellStyle.BackColor = Color.FromArgb(255, 205, 210); // 浅红色背景 #FFCDD2
row.DefaultCellStyle.ForeColor = Color.FromArgb(198, 40, 40); // 深红色文字
// row.DefaultCellStyle.Font = new Font(row.DefaultCellStyle.Font, FontStyle.Bold);
}
else
{
// 根据状态设置颜色
switch (station.Status)
{
case ChargeStationStatus.Idle:
row.DefaultCellStyle.BackColor = Color.FromArgb(232, 245, 233); // 浅绿色 #E8F5E9
// row.DefaultCellStyle.ForeColor = Color.FromArgb(46, 125, 50); // 深绿色文字
break;
case ChargeStationStatus.Charging:
row.DefaultCellStyle.BackColor = Color.FromArgb(200, 230, 201); // 亮绿色 #C8E6C9
// row.DefaultCellStyle.ForeColor = Color.FromArgb(27, 94, 32); // 深绿色文字
break;
case ChargeStationStatus.Fault:
row.DefaultCellStyle.BackColor = Color.FromArgb(255, 205, 210); // 浅红色 #FFCDD2
// row.DefaultCellStyle.ForeColor = Color.FromArgb(198, 40, 40); // 深红色文字
break;
case ChargeStationStatus.Battery:
row.DefaultCellStyle.BackColor = Color.FromArgb(238, 238, 238); // 浅灰色 #EEEEEE
// row.DefaultCellStyle.ForeColor = Color.FromArgb(97, 97, 97); // 深灰色文字
break;
}
}
}
// 更新标题和统计
UpdateTitleWithFilter(stations.Count);
}
private void btnStrategyConfig_Click(object sender, EventArgs e)
{
try
{
// 打开充电策略配置界面
var strategyConfigForm = new ChargeStrategyConfigForm();
strategyConfigForm.ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show($"打开策略配置界面失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void btnCommMonitor_Click(object sender, EventArgs e)
{
try
{
// 通讯监控窗口仅允许单实例
if (communicationMonitorForm == null || communicationMonitorForm.IsDisposed)
{
communicationMonitorForm = new CommunicationMonitorForm();
communicationMonitorForm.FormClosed += (s, args) => communicationMonitorForm = null;
communicationMonitorForm.Show();
}
else
{
if (communicationMonitorForm.WindowState == FormWindowState.Minimized)
{
communicationMonitorForm.WindowState = FormWindowState.Normal;
}
communicationMonitorForm.BringToFront();
communicationMonitorForm.Activate();
}
}
catch (Exception ex)
{
MessageBox.Show($"打开通讯监控界面失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void btnAlarmConfig_Click(object sender, EventArgs e)
{
try
{
// 打开报警配置界面
var alarmConfigForm = new AlarmConfigManagementForm();
alarmConfigForm.ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show($"打开报警配置失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void btnExport_Click(object sender, EventArgs e)
{
try
{
var saveDialog = new SaveFileDialog
{
Filter = "JSON文件|*.json|CSV文件|*.csv",
FileName = $"ChargeStations_{DateTime.Now:yyyyMMddHHmmss}"
};
if (saveDialog.ShowDialog() == DialogResult.OK)
{
var stations = dataService.GetAllStations();
if (saveDialog.FilterIndex == 1) // JSON
{
var json = Newtonsoft.Json.JsonConvert.SerializeObject(stations, Newtonsoft.Json.Formatting.Indented);
System.IO.File.WriteAllText(saveDialog.FileName, json);
}
else // CSV
{
var csv = "编号,名称,类型,IP地址,端口,电压,电流,功率,状态,启用,停靠车的类型,站点ID,备注\n";
foreach (var s in stations)
{
csv += $"{s.StationId},{s.Name},{GetTypeText(s.Type)},{s.IpAddress},{s.Port},{s.SetVoltage},{s.SetElectricCurrent},{s.Power},{GetStatusText(s.Status)},{(s.Enabled ? "" : "")},{s.GroupCarType},{s.SiteId},{s.Remarks}\n";
}
System.IO.File.WriteAllText(saveDialog.FileName, csv, System.Text.Encoding.UTF8);
}
MessageBox.Show("导出成功!", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception ex)
{
MessageBox.Show($"导出失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}