refactor: 插件窗体由 static 单例状态改为实例字段(对齐 TextViewer)

将 10 个 CycleGUI 窗体/管理器从进程级 static 单例状态改为实例字段 + 实例方法,
消除本地端/Web 端共享同一可变状态的隐患(对齐 TextViewer 正例)。

每个类保留一个 private static _instance 单实例持有者;静态入口 Open()/OpenViewer()
与实例 Show() 均转发到该实例,调用方零改动、单实例“置前”行为不变。

涉及:ChargeStationManagementForm、ChargeStrategyConfigForm、CommunicationMonitorForm、
AlarmConfigManagementForm、ButtonBoxManager、DoorManager、DoorMonitor、
LoopViewer、DeliveryViewer、TrafficInterlockViewer。

构建:dotnet build StandardScene.sln --no-incremental → 0 错误,30 警告(与基线一致,无新增)。
This commit is contained in:
zhaowei.huang
2026-06-26 15:31:02 +08:00
parent a0dc1e6cd0
commit 54cda958db
10 changed files with 297 additions and 257 deletions
@@ -18,29 +18,33 @@ namespace StandardScene.ExtendDevice.Door
public class DoorManager
{
private const string DataFileName = "DoorConfig.json";
private static string DataFilePath => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DataFileName);
private static readonly object SaveLock = new object();
private string DataFilePath => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DataFileName);
private readonly object SaveLock = new object();
private static Panel _panel;
private static List<DoorControllerModel> _controllers = new List<DoorControllerModel>();
private static int _selectedCtrlIdx = -1;
private static int _selectedDoorIdx = -1;
private static string _status = "";
private Panel _panel;
private List<DoorControllerModel> _controllers = new List<DoorControllerModel>();
private int _selectedCtrlIdx = -1;
private int _selectedDoorIdx = -1;
private string _status = "";
private static string _ctrlIp = "";
private static string _ctrlPort = "502";
private static string _ctrlIndex = "";
private static int _typeIdx;
private static string[] _typeNames = Array.Empty<string>();
private string _ctrlIp = "";
private string _ctrlPort = "502";
private string _ctrlIndex = "";
private int _typeIdx;
private string[] _typeNames = Array.Empty<string>();
private static string _doorIndex = "";
private static string _doorCtrlAddr = "";
private static string _doorOpenAddr = "";
private static bool _doorNoControl;
private string _doorIndex = "";
private string _doorCtrlAddr = "";
private string _doorOpenAddr = "";
private bool _doorNoControl;
public static void OpenViewer() => Open();
public static void Open()
public static void Open() => (_instance ??= new DoorManager()).OpenCore();
private static DoorManager _instance;
private void OpenCore()
{
if (_panel != null)
{
@@ -148,17 +152,17 @@ namespace StandardScene.ExtendDevice.Door
});
}
private static DoorControllerModel GetSelectedController() =>
private DoorControllerModel GetSelectedController() =>
_selectedCtrlIdx >= 0 && _selectedCtrlIdx < _controllers.Count ? _controllers[_selectedCtrlIdx] : null;
private static DoorModel GetSelectedDoor()
private DoorModel GetSelectedDoor()
{
var ctrl = GetSelectedController();
return ctrl != null && _selectedDoorIdx >= 0 && _selectedDoorIdx < ctrl.Doors.Count
? ctrl.Doors[_selectedDoorIdx] : null;
}
private static string[] DiscoverTypes()
private string[] DiscoverTypes()
{
try
{
@@ -179,7 +183,7 @@ namespace StandardScene.ExtendDevice.Door
}
}
private static void LoadData()
private void LoadData()
{
try
{
@@ -196,7 +200,7 @@ namespace StandardScene.ExtendDevice.Door
}
}
private static void SaveData()
private void SaveData()
{
var json = _controllers.ToJson();
var path = DataFilePath;
@@ -215,7 +219,7 @@ namespace StandardScene.ExtendDevice.Door
});
}
private static void LoadControllerFields(DoorControllerModel c)
private void LoadControllerFields(DoorControllerModel c)
{
_ctrlIp = c.Ip;
_ctrlPort = c.Port.ToString();
@@ -224,7 +228,7 @@ namespace StandardScene.ExtendDevice.Door
if (_typeIdx < 0) _typeIdx = 0;
}
private static void ClearControllerFields()
private void ClearControllerFields()
{
_ctrlIp = "";
_ctrlPort = "502";
@@ -232,7 +236,7 @@ namespace StandardScene.ExtendDevice.Door
_typeIdx = 0;
}
private static void LoadDoorFields(DoorModel d)
private void LoadDoorFields(DoorModel d)
{
_doorIndex = d.Index.ToString();
_doorCtrlAddr = d.ControlAddress.ToString();
@@ -240,7 +244,7 @@ namespace StandardScene.ExtendDevice.Door
_doorNoControl = d.NoControl;
}
private static void ClearDoorFields()
private void ClearDoorFields()
{
_doorIndex = "";
_doorCtrlAddr = "";
@@ -248,7 +252,7 @@ namespace StandardScene.ExtendDevice.Door
_doorNoControl = false;
}
private static void AddController()
private void AddController()
{
if (!TryParseControllerInput(out var index, out var ip, out var port, out var type, false, out var err))
{
@@ -266,7 +270,7 @@ namespace StandardScene.ExtendDevice.Door
_panel?.Repaint();
}
private static void SaveController()
private void SaveController()
{
var cur = GetSelectedController();
if (cur == null) { CycleUiHelper.Alert("提示", "请先选择要保存的门控制器"); return; }
@@ -288,7 +292,7 @@ namespace StandardScene.ExtendDevice.Door
_panel?.Repaint();
}
private static void ConfirmDeleteController()
private void ConfirmDeleteController()
{
var cur = GetSelectedController();
if (cur == null) { CycleUiHelper.Alert("提示", "请选择要删除的门控制器"); return; }
@@ -305,7 +309,7 @@ namespace StandardScene.ExtendDevice.Door
});
}
private static void AddDoor()
private void AddDoor()
{
var ctrl = GetSelectedController();
if (ctrl == null) { CycleUiHelper.Alert("提示", "请先选择门控制器"); return; }
@@ -330,7 +334,7 @@ namespace StandardScene.ExtendDevice.Door
_panel?.Repaint();
}
private static void SaveDoor()
private void SaveDoor()
{
var ctrl = GetSelectedController();
var door = GetSelectedDoor();
@@ -352,7 +356,7 @@ namespace StandardScene.ExtendDevice.Door
_panel?.Repaint();
}
private static void ConfirmDeleteDoor()
private void ConfirmDeleteDoor()
{
var ctrl = GetSelectedController();
var door = GetSelectedDoor();
@@ -368,7 +372,7 @@ namespace StandardScene.ExtendDevice.Door
});
}
private static bool TryParseControllerInput(out int index, out string ip, out int port, out string type, bool requireSelection, out string err)
private bool TryParseControllerInput(out int index, out string ip, out int port, out string type, bool requireSelection, out string err)
{
index = 0; ip = ""; port = 502; type = ""; err = "";
ip = string.IsNullOrWhiteSpace(_ctrlIp) ? "192.168.1.100" : _ctrlIp.Trim();
@@ -384,7 +388,7 @@ namespace StandardScene.ExtendDevice.Door
return true;
}
private static bool TryParseDoorInput(out int index, out ushort cAddr, out ushort oAddr, bool requireSelection, out string err)
private bool TryParseDoorInput(out int index, out ushort cAddr, out ushort oAddr, bool requireSelection, out string err)
{
index = 0; cAddr = 0; oAddr = 0; err = "";
var ctrl = GetSelectedController();
@@ -401,7 +405,7 @@ namespace StandardScene.ExtendDevice.Door
return true;
}
private static bool IsValidIp(string ip)
private bool IsValidIp(string ip)
{
if (string.IsNullOrWhiteSpace(ip)) return false;
var pattern = @"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";
@@ -20,13 +20,17 @@ namespace StandardScene.ExtendDevice.Door
{
private const string TableId = "door-monitor-list";
private static readonly Color SelectedRowColor = Color.FromArgb(230, 240, 255);
private readonly Color SelectedRowColor = Color.FromArgb(230, 240, 255);
private static Panel _panel;
private static (int ControllerIndex, int DoorIndex)? _selectedDoor;
private Panel _panel;
private (int ControllerIndex, int DoorIndex)? _selectedDoor;
/// <summary>打开(或置前)门控监控面板。</summary>
public static void Open()
public static void Open() => (_instance ??= new DoorMonitor()).OpenCore();
private static DoorMonitor _instance;
private void OpenCore()
{
if (_panel != null)
{
@@ -105,21 +109,21 @@ namespace StandardScene.ExtendDevice.Door
});
}
private static void LabelCell(PanelBuilder.Row row, DoorMission.DoorMonitorSnapshotItem door, string text)
private void LabelCell(PanelBuilder.Row row, DoorMission.DoorMonitorSnapshotItem door, string text)
{
if (row.Label(text))
_selectedDoor = (door.ControllerIndex, door.DoorIndex);
}
private static DoorMission GetMission() =>
private DoorMission GetMission() =>
SimpleProject.proj?.Missions?.OfType<DoorMission>().FirstOrDefault();
private static bool IsRowSelected(DoorMission.DoorMonitorSnapshotItem door) =>
private bool IsRowSelected(DoorMission.DoorMonitorSnapshotItem door) =>
_selectedDoor.HasValue
&& _selectedDoor.Value.ControllerIndex == door.ControllerIndex
&& _selectedDoor.Value.DoorIndex == door.DoorIndex;
private static string GetDoorInfoText(IReadOnlyList<DoorMission.DoorMonitorSnapshotItem> snapshot)
private string GetDoorInfoText(IReadOnlyList<DoorMission.DoorMonitorSnapshotItem> snapshot)
{
if (!_selectedDoor.HasValue)
return "请选择要控制的门";
@@ -133,7 +137,7 @@ namespace StandardScene.ExtendDevice.Door
return $"控制器编码: {door.ControllerIndex}, 门编码: {door.DoorIndex}";
}
private static bool CanCloseSelected(DoorMission mission)
private bool CanCloseSelected(DoorMission mission)
{
if (!_selectedDoor.HasValue || mission == null)
return true;
@@ -142,18 +146,18 @@ namespace StandardScene.ExtendDevice.Door
return cars.Count == 0;
}
private static string FormatState(DoorState state) =>
private string FormatState(DoorState state) =>
state == DoorState.Open ? "打开" : state == DoorState.Closed ? "关闭" : "未知";
private static string FormatManualRemain(DoorMission.DoorMonitorSnapshotItem door) =>
private string FormatManualRemain(DoorMission.DoorMonitorSnapshotItem door) =>
door.Source == DoorMission.ControlSource.Manual && door.ManualRemainingSeconds.HasValue
? Math.Ceiling(door.ManualRemainingSeconds.Value).ToString()
: "-";
private static string FormatCars(DoorMission.DoorMonitorSnapshotItem door) =>
private string FormatCars(DoorMission.DoorMonitorSnapshotItem door) =>
door.CarsInArea.Count > 0 ? string.Join(", ", door.CarsInArea) : "无";
private static void OpenSelectedDoor()
private void OpenSelectedDoor()
{
if (!_selectedDoor.HasValue)
{
@@ -180,7 +184,7 @@ namespace StandardScene.ExtendDevice.Door
}
}
private static void CloseSelectedDoor()
private void CloseSelectedDoor()
{
if (!_selectedDoor.HasValue)
{
@@ -213,7 +217,7 @@ namespace StandardScene.ExtendDevice.Door
}
}
private static void ClearSelectedCars()
private void ClearSelectedCars()
{
if (!_selectedDoor.HasValue)
{