将 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 项)暂未处理,留待单独任务。
260 lines
9.7 KiB
C#
260 lines
9.7 KiB
C#
using System;
|
|
using CycleGUI;
|
|
using StandardScene.Utils;
|
|
|
|
namespace StandardScene.Charge
|
|
{
|
|
/// <summary>
|
|
/// 充电策略配置界面(CycleGUI 版,替代原 WinForms 窗体)。
|
|
/// </summary>
|
|
public class ChargeStrategyConfigForm
|
|
{
|
|
private static Panel _panel;
|
|
private static readonly ChargeStrategyConfigService ConfigService = ChargeStrategyConfigService.Instance;
|
|
|
|
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()
|
|
{
|
|
if (_panel != null)
|
|
{
|
|
try
|
|
{
|
|
_panel.BringToFront();
|
|
return;
|
|
}
|
|
catch
|
|
{
|
|
_panel = null;
|
|
}
|
|
}
|
|
|
|
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 =>
|
|
{
|
|
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;
|
|
}
|
|
});
|
|
}
|
|
|
|
private static bool TryLoadConfig()
|
|
{
|
|
try
|
|
{
|
|
_config = ConfigService.LoadConfig();
|
|
ApplyConfigToUi(_config);
|
|
_status = "配置加载成功";
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
CycleUiHelper.Alert("错误", $"加载配置失败: {ex.Message}");
|
|
_status = "配置加载失败";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static void ApplyConfigToUi(ChargeStrategyConfig config)
|
|
{
|
|
_mustChargeSoc = (float)config.MustChargeSoc;
|
|
_idleChargeSoc = (float)config.IdleChargeSoc;
|
|
_taskAvailableSoc = (float)config.TaskAvailableSoc;
|
|
_fullChargeSoc = (float)config.FullChargeSoc;
|
|
_allowInterruptSoc = (float)config.AllowInterruptSoc;
|
|
|
|
_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;
|
|
}
|
|
|
|
private static void ApplyUiToConfig()
|
|
{
|
|
_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)
|
|
{
|
|
errorMessage = "必充电量必须小于空闲充电电量";
|
|
return false;
|
|
}
|
|
|
|
if (_taskAvailableSoc <= _mustChargeSoc)
|
|
{
|
|
errorMessage = "任务可用电量必须大于必充电量";
|
|
return false;
|
|
}
|
|
|
|
if (_fullChargeSoc < _idleChargeSoc)
|
|
{
|
|
errorMessage = "满电电量必须大于等于空闲充电电量";
|
|
return false;
|
|
}
|
|
|
|
if (_allowInterruptSoc <= _mustChargeSoc)
|
|
{
|
|
errorMessage = "允许中断电量必须大于必充电量";
|
|
return false;
|
|
}
|
|
|
|
errorMessage = string.Empty;
|
|
return true;
|
|
}
|
|
|
|
private static void TrySave(bool closeAfterSave)
|
|
{
|
|
ApplyUiToConfig();
|
|
|
|
if (!ValidateSocRanges(out var socError))
|
|
{
|
|
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 static void RestoreDefaults()
|
|
{
|
|
CycleUiHelper.ConfirmThen("确定要恢复默认配置吗?当前配置将被覆盖。", () =>
|
|
{
|
|
_config = ChargeStrategyConfig.CreateDefault();
|
|
ApplyConfigToUi(_config);
|
|
_status = "已恢复默认配置(未保存)";
|
|
_panel?.Repaint();
|
|
});
|
|
}
|
|
}
|
|
}
|