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:
zhaowei.huang
2026-06-26 15:00:53 +08:00
parent c8e540d272
commit a0dc1e6cd0
91 changed files with 3946 additions and 15419 deletions
@@ -0,0 +1,102 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace StandardScene.CarTypes
{
/// <summary>
/// Coder 字段袋元数据导出。
/// <para>在 StandardScene 程序集内执行反射,可正确读取 internal Fields 类(如 BasicTrackFields)。</para>
/// </summary>
public static class CoderFieldsMetadata
{
/// <summary>
/// 描述单个 Fields 类型的字段清单(含继承链上的 public 字段)。
/// </summary>
/// <param name="fieldsType">Fields 字段袋类型</param>
/// <returns>供 SimpleLite API 序列化的匿名结构;fieldsType 为 null 时返回 null</returns>
public static object? Describe(Type? fieldsType)
{
if (fieldsType == null)
{
return null;
}
var fieldInfos = CollectPublicFieldInfos(fieldsType);
return new
{
typeName = fieldsType.FullName ?? fieldsType.Name,
shortName = fieldsType.Name,
assemblyName = fieldsType.Assembly.GetName().Name ?? "",
baseTypeName = fieldsType.BaseType?.FullName,
fields = fieldInfos.Select(fi => new
{
name = fi.Name,
typeName = fi.FieldType.FullName ?? fi.FieldType.Name,
defaultValue = ReadFieldDefault(fieldsType, fi)
}).ToArray()
};
}
/// <summary>
/// 自基类到派生类收集 public 实例字段。
/// </summary>
static List<FieldInfo> CollectPublicFieldInfos(Type type)
{
var ordered = new List<FieldInfo>();
var seen = new HashSet<string>(StringComparer.Ordinal);
var chain = new List<Type>();
for (var t = type; t != null && t != typeof(object); t = t.BaseType)
{
chain.Insert(0, t);
}
const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
foreach (var t in chain)
{
foreach (var fi in t.GetFields(flags))
{
if (fi.IsStatic || !seen.Add(fi.Name))
{
continue;
}
ordered.Add(fi);
}
}
return ordered;
}
static object? ReadFieldDefault(Type fieldsType, FieldInfo fi)
{
try
{
var instance = Activator.CreateInstance(fieldsType, true);
return NormalizeDefaultValue(fi.GetValue(instance));
}
catch
{
return null;
}
}
static object? NormalizeDefaultValue(object? value)
{
if (value == null)
{
return null;
}
return value switch
{
string or bool or int or long or short or byte or uint or ulong or float or double or decimal => value,
_ => value.ToString()
};
}
}
}
+5 -30
View File
@@ -1,5 +1,5 @@
using AMRScene1;
using SimpleLite;
using SimpleLite.Rendering;
using SimpleLite.RCS;
using SimpleLite.RCS.CarTypes;
using SimpleLite.CADTools;
@@ -23,7 +23,8 @@ using System.Numerics;
using System.Runtime.InteropServices.ComTypes;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using StandardScene.Utils;
using SimpleLite;
namespace AMRScene1
{
@@ -36,12 +37,10 @@ namespace AMRScene1
class DummyCarSiteField
{
public bool Shelf = false;
}
class DummyCarPlanField
{
public string action = "/";
}
[TemplateTrackCoderSettings(
@@ -118,14 +117,6 @@ namespace AMRScene1
haveCoordination = true
};
}
public override void rightClickAction(float mouseX, float mouseY)
{
x = mouseX;
y = mouseY;
}
public class AGV: AGVInterface
{
@@ -518,7 +509,7 @@ namespace AMRScene1
{
Task.Run(() =>
{
MessageBox.Show("go?");
CycleUiHelper.Alert("提示", "go?");
go();
});
});
@@ -608,7 +599,7 @@ namespace AMRScene1
string tag = InputBox.ResultValue;
if (tag.Contains(""))
{
MessageBox.Show("需要切换英文输入法输入:");
CycleUiHelper.Alert("提示", "需要切换英文输入法输入:");
return;
}
if (!string.IsNullOrEmpty(tag) && tag.Contains(":"))
@@ -649,22 +640,6 @@ namespace AMRScene1
Task.Run(hijiack_fun);
}
[MethodMember(Name = "设置位姿", Description = "拖拽以设置位姿")]
public void SetPosition()
{
SimpleMonitor.registerDownevent((sender, args) =>
{
x = SimpleMonitor.mouseX;
y = SimpleMonitor.mouseY;
},null, (sender, args) =>
{
th = (float)(Math.Atan2(SimpleMonitor.mouseY - y, SimpleMonitor.mouseX - x) / Math.PI * 180);
}, (sender, args) => SimpleMonitor.clearDownevent());
}
[MethodMember(Name = "走到指定位置并设置Escape", Description = "点一个位置,再点一个位置")]
public void GoEscaped()
{
-46
View File
@@ -1,46 +0,0 @@
namespace StandardScene
{
partial class VehicleMonitor
{
/// <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()
{
this.SuspendLayout();
//
// VehicleMonitor
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1800, 900);
this.Name = "VehicleMonitor";
this.Text = "车辆状态监控系统";
this.ResumeLayout(false);
}
#endregion
}
}
File diff suppressed because it is too large Load Diff
@@ -15,7 +15,6 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace StandardScene.Chained
{
@@ -1510,7 +1509,7 @@ namespace StandardScene.Chained
public JsonFileTaskStrategy(string jsonPath = null)
{
JsonPath = string.IsNullOrWhiteSpace(jsonPath)
? Path.Combine(Application.StartupPath, "tasklist.json")
? Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "tasklist.json")
: jsonPath;
EnsureWatcher();
+165 -161
View File
@@ -1,13 +1,10 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CycleGUI;
using StandardScene.Model;
using SimpleLite;
using SimpleCore;
@@ -17,35 +14,162 @@ using static StandardScene.Chained.ChainedDeliveryMission;
namespace StandardScene.Chained
{
public partial class DeliveryViewer : Form
/// <summary>
/// 搬运任务管理界面(CycleGUI 版,替代原 WinForms <c>DeliveryViewer</c> 窗体)。
/// <list type="bullet">
/// <item>单实例:再次打开则把已有面板置前。</item>
/// <item>约每 1s 节流刷新任务快照(在渲染线程内节流,避免并发),面板 500ms 准实时重绘。</item>
/// <item>每行提供「取消 / 重发 / 换车重发」按钮(带二次确认),超时任务整行高亮。</item>
/// </list>
/// 保留可实例化 + <see cref="Show"/> 以兼容既有调用 <c>new DeliveryViewer().Show()</c>。
/// </summary>
public class DeliveryViewer
{
private const int OverdueMinutesThreshold = 10000; // 约7天视为超时
private const int DisplayColumnIndexOverdueFlag = 9;
private const int OverdueMinutesThreshold = 10000; // 约 7 天视为超时
private const string TableId = "delivery-task-list";
private static readonly HttpClient SharedHttpClient = new HttpClient();
/// <summary>选中行的背景色</summary>
private static readonly Color SelectedRowBackColor = Color.FromArgb(220, 230, 250);
/// <summary>缓存选中行索引,避免在 RetrieveVirtualItem 中访问 SelectedIndices 引发递归</summary>
private readonly HashSet<int> _selectedIndicesCache = new HashSet<int>();
/// <summary>超时任务整行底色(深色主题下的暗红,醒目但不刺眼)。</summary>
private static readonly Color OverdueRowColor = Color.FromArgb(255, 90, 36, 36);
private ListViewItem _item = null;
private static Panel _panel;
private static bool _showFinished = true; // 显示已完成任务
private static bool _showAbolished = true; // 显示废止任务(Error / Canceled / Terminated
public DeliveryViewer()
// 渲染快照:由后台线程按 FlushInterval 刷新,渲染线程只读引用;锁/文件 IO 绝不放在渲染线程,避免界面卡死。
private static volatile List<Delivery> _snapshot = new List<Delivery>();
private static volatile bool _refreshing;
private static DateTime _lastFlush = DateTime.MinValue;
private static readonly TimeSpan FlushInterval = TimeSpan.FromSeconds(1);
private static volatile string _status = "";
/// <summary>打开(或置前)任务管理面板。兼容原 <c>new DeliveryViewer().Show()</c> 调用方式。</summary>
public void Show() => Open();
/// <summary>打开(或置前)任务管理面板。</summary>
public static void Open()
{
InitializeComponent();
if (_panel != null)
{
try
{
_panel.BringToFront();
return;
}
catch
{
_panel = null;
}
}
var panel = GUI.DeclarePanel()
.ShowTitle("任务列表")
.SetDefaultDocking(Panel.Docking.None)
.InitSize(1500, 620) // 列宽按内容自适应(SizingFixedFit),给足初始宽度避免 10 列横向拥挤
.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;
}
// 过滤开关:改变时强制立即刷新一次(不必等节流窗口)。
if (pb.CheckBox("显示已完成任务", ref _showFinished)) _lastFlush = DateTime.MinValue;
pb.SameLine(16);
if (pb.CheckBox("显示废止的任务(Error / Canceled / Terminated", ref _showAbolished)) _lastFlush = DateTime.MinValue;
EnsureSnapshotFresh();
var items = _snapshot;
pb.Label($"共 {items.Count} 个任务(超时任务高亮置顶)");
pb.Table(TableId,
new[] { "任务号", "小车", "取货点", "放货点", "任务状态", "下发时间", "执行时间", "结束时间", "优先级", "操作" },
items.Count, (row, i) =>
{
var dd = items[i];
if (IsOverdue(dd)) row.SetColor(OverdueRowColor);
row.Label($"{dd.Id}");
row.Label(dd.UsingCar?.name ?? "");
row.Label($"{dd.Src}-{SafeSiteName(dd.Src)}");
row.Label($"{dd.Dst}-{SafeSiteName(dd.Dst)}");
row.Label($"{dd.GetStatus()}");
row.Label($"{dd.CreateTime:yyyy-MM-dd HH:mm:ss}");
row.Label($"{dd.StartTime:yyyy-MM-dd HH:mm:ss}");
row.Label($"{dd.FinishTime:yyyy-MM-dd HH:mm:ss}");
row.Label($"{dd.Priority}");
var op = row.ButtonGroup(
new[] { "取消", "重发", "换车" },
new[] { "取消任务", "重发任务", "换车重发任务" });
var taskCode = dd.Id;
// 业务操作含文件 IO 与锁竞争,统一用 Task.Run 放后台执行,绝不阻塞渲染线程(否则界面卡死)。
if (op == 0) CycleUiHelper.ConfirmThen($"是否结束任务 {taskCode}", () => Task.Run(() => CancelDelivery(taskCode)));
else if (op == 1) CycleUiHelper.ConfirmThen($"是否重发任务 {taskCode}", () => Task.Run(() => ResendDelivery(taskCode)));
else if (op == 2) CycleUiHelper.ConfirmThen($"是否换车重发任务 {taskCode}", () => Task.Run(() => ChangeCarResendDelivery(taskCode)));
}, height: 18, enableSearch: true);
if (!string.IsNullOrEmpty(_status))
{
pb.Separator();
pb.Label(_status);
}
// 节流重绘:任务监控无需高帧率,约 500ms 刷新一次即可保持准实时,显著降低 CPU。
pb.Panel.Repaint(repaintTimeMs: 500);
});
}
private readonly ContextMenuStrip strip = new ContextMenuStrip();
private static bool IsOverdue(Delivery dd) =>
(DateTime.Now - dd.CreateTime).TotalMinutes > OverdueMinutesThreshold;
private void DeliveryViewer_Load(object sender, EventArgs e)
/// <summary>
/// 渲染线程调用:到达刷新间隔且无在途刷新时,<b>在后台线程</b>重新拉取任务快照(超时任务置顶)。
/// 业务侧的锁与文件 IO 一律放到后台,渲染线程只读 <see cref="_snapshot"/> 引用,避免界面卡死。
/// </summary>
private static void EnsureSnapshotFresh()
{
strip.Items.Clear();
strip.Items.Add("取消任务", null, CancelClick);
strip.Items.Add("重发任务", null, ResendClick);
strip.Items.Add("换车重发任务", null, ChangeCarResendClick);
currentTaskList.ContextMenuStrip = strip;
if (_refreshing) return;
if (DateTime.Now - _lastFlush < FlushInterval) return;
_lastFlush = DateTime.Now;
_refreshing = true;
// 捕获当前过滤条件,避免后台读取过程中被 UI 改动。
bool showFinished = _showFinished, showAbolished = _showAbolished;
Task.Run(() =>
{
try
{
var list = new List<Delivery>();
foreach (var cdm in SimpleProject.proj.Missions.OfType<ChainedDeliveryMission>())
list.AddRange(cdm.GetDeliveries(showFinished, showAbolished, showAbolished, showAbolished));
// 与原窗体一致:超时任务排在最前。
_snapshot = list.OrderByDescending(d => IsOverdue(d) ? 1 : 0).ToList();
}
catch (Exception ex)
{
Diagnosis.Post($"DeliveryViewer 刷新异常: {ExceptionFormatter.FormatEx(ex)}");
}
finally
{
_refreshing = false;
}
});
}
private List<string[]> _listDeliveries = new List<string[]>();
private static string SafeSiteName(int siteId)
{
try { return SimpleLib.GetSite(siteId)?.name ?? ""; }
catch { return ""; }
}
/// <summary>将任务标记为已取消(Canceled)。</summary>
private static void MarkDeliveryCanceled(Delivery d)
@@ -93,93 +217,8 @@ namespace StandardScene.Chained
}
}
protected virtual string[] GetDisplayContent(Delivery dd)
private static void ResendDelivery(string taskCode)
{
var srcName =SimpleLib.GetSite(dd.Src).name;
var dstName =SimpleLib.GetSite(dd.Dst).name;
var now = DateTime.Now;
var usingCar = dd.UsingCar == null ? string.Empty : dd.UsingCar.name;
return
[
$"{dd.Id}",
$"{usingCar}",
$"{dd.Src}-{srcName}",
$"{dd.Dst}-{dstName}",
$"{dd.GetStatus()}",
$"{dd.CreateTime:yyyy-mm-dd HH:mm:ss:fff}",
$"{dd.StartTime:yyyy-mm-dd HH:mm:ss:fff}",
$"{dd.FinishTime:yyyy-mm-dd HH:mm:ss:fff}",
$"{dd.Priority}",
$"{((now - dd.CreateTime).TotalMinutes > OverdueMinutesThreshold ? 1 : 0)}",
$"{dd.Id}"
];
}
private void TaskFlush()
{
_listDeliveries.Clear();
try
{
foreach (var cdm in SimpleProject.proj.Missions.OfType<ChainedDeliveryMission>())
foreach (var dd in cdm.GetDeliveries(checkBox1.Checked, checkBox2.Checked,checkBox2.Checked,checkBox2.Checked))
_listDeliveries.Add(GetDisplayContent(dd));
if (_listDeliveries.Count > 0)
{
var len = _listDeliveries[0].Length;
if (len > 0) _listDeliveries = _listDeliveries.OrderByDescending(p => int.Parse(p[len - 2])).ToList();
}
}
catch (Exception ex)
{
Diagnosis.Post($"TaskFlush 异常: {ExceptionFormatter.FormatEx(ex)}");
}
}
private void timer1_Tick(object sender, EventArgs e)
{
try
{
TaskFlush();
currentTaskList.VirtualListSize = _listDeliveries.Count;
currentTaskList.Invalidate();
}
catch (Exception ex)
{
Diagnosis.Post($"timer1_Tick 异常: {ExceptionFormatter.FormatEx(ex)}");
}
}
private void currentTaskList_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
try
{
var n = e.ItemIndex;
e.Item = new ListViewItem(_listDeliveries[n]);
if (_listDeliveries[n].Length > DisplayColumnIndexOverdueFlag && _listDeliveries[n][DisplayColumnIndexOverdueFlag] == "1")
e.Item.ForeColor = Color.Red;
if (_selectedIndicesCache.Contains(n))
e.Item.BackColor = SelectedRowBackColor;
}
catch (Exception)
{
e.Item = new ListViewItem(["", "", "", "", "", "", "", "", ""]);
}
}
private void currentTaskList_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Right) return;
_item = currentTaskList.GetItemAt(e.X, e.Y);
}
private void ResendClick(object sender, EventArgs e)
{
if (_item == null) return;
string taskCode = _item.Text;
try
{
var cdm = SimpleProject.proj.Missions.OfType<TransportMission>().FirstOrDefault();
@@ -189,44 +228,40 @@ namespace StandardScene.Chained
.FirstOrDefault(s => s.Id == taskCode);
if (d == null)
{
MessageBox.Show("列表中不存在目标任务", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
_status = $"重发失败:列表中不存在任务 {taskCode}";
return;
}
var ms = MessageBox.Show($"是否重发任务--{taskCode}", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
if (ms != System.Windows.Forms.DialogResult.OK) return;
if (!MarkDeliveryWaiting(d, clearCarForChange: false))
{
MessageBox.Show("重发任务失败:当前状态不允许重发", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
_status = "重发任务失败:当前状态不允许重发";
return;
}
// 状态已改为 Waiting,持久化
cdm.PersistDelivery(d);
_status = $"已重发任务 {taskCode}";
}
catch (Exception)
catch (Exception ex)
{
MessageBox.Show("列表中不存在目标任务", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
_status = $"重发任务 {taskCode} 异常,详见日志";
Diagnosis.Post($"重发任务 {taskCode} 异常: {ExceptionFormatter.FormatEx(ex)}");
}
}
private void CancelClick(object sender, EventArgs e)
private static void CancelDelivery(string taskCode)
{
if (_item == null) return;
string str = _item.Text;
try
{
var cdm = SimpleProject.proj.Missions.OfType<TransportMission>().FirstOrDefault();
if (cdm == null) return;
var d = cdm.GetDeliveries(true, true, true, true)
.OfType<TransportDelivery>()
.FirstOrDefault(s => s.Id == str);
.FirstOrDefault(s => s.Id == taskCode);
if (d == null)
{
MessageBox.Show("列表中不存在目标任务", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
_status = $"取消失败:列表中不存在任务 {taskCode}";
return;
}
var ms = MessageBox.Show($"是否结束任务--{str}", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
if (ms != System.Windows.Forms.DialogResult.OK || d.IsFinished()) return;
if (d.IsFinished()) return;
// 1) 状态上将任务标记为已取消
MarkDeliveryCanceled(d);
@@ -242,17 +277,17 @@ namespace StandardScene.Chained
// 3) 持久化已取消状态
cdm.PersistDelivery(d);
_status = $"已结束任务 {taskCode}";
}
catch (Exception ex)
{
Diagnosis.Post($"结束任务 {str} 异常: {ExceptionFormatter.FormatEx(ex)}");
_status = $"结束任务 {taskCode} 异常,详见日志";
Diagnosis.Post($"结束任务 {taskCode} 异常: {ExceptionFormatter.FormatEx(ex)}");
}
}
private void ChangeCarResendClick(object sender, EventArgs e)
private static void ChangeCarResendDelivery(string taskCode)
{
if (_item == null) return;
string taskCode = _item.Text;
try
{
var cdm = SimpleProject.proj.Missions.OfType<TransportMission>().FirstOrDefault();
@@ -262,55 +297,24 @@ namespace StandardScene.Chained
.FirstOrDefault(s => s.Id == taskCode);
if (d == null)
{
MessageBox.Show("列表中不存在目标任务", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
_status = $"换车重发失败:列表中不存在任务 {taskCode}";
return;
}
var ms = MessageBox.Show($"是否换车重发任务--{taskCode}", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
if (ms != System.Windows.Forms.DialogResult.OK) return;
if (!MarkDeliveryWaiting(d, clearCarForChange: true))
{
MessageBox.Show("换车重发失败:仅当任务状态为 Suspended 或 Waiting 且未处于放货阶段时才允许换车重发", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
_status = "换车重发失败:仅当任务状态为 Suspended 或 Waiting 且未处于放货阶段时才允许换车重发";
return;
}
// 状态已改为 Waiting 且 UsingCar 已清空,持久化
cdm.PersistDelivery(d);
_status = $"已换车重发任务 {taskCode}";
}
catch (Exception ex)
{
_status = $"换车重发任务 {taskCode} 异常,详见日志";
Diagnosis.Post($"换车重发任务 {taskCode} 异常: {ExceptionFormatter.FormatEx(ex)}");
MessageBox.Show("换车重发任务异常,请查看日志", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
private void DeliveryViewer_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
this.Visible = false;
timer1.Stop();
}
}
protected override void SetVisibleCore(bool value)
{
if (!IsHandleCreated && value)
CreateHandle();
bool wasVisible = Visible;
base.SetVisibleCore(value);
if (value && !wasVisible)
timer1.Start();
}
private void currentTaskList_SelectedIndexChanged(object sender, EventArgs e)
{
_selectedIndicesCache.Clear();
foreach (int i in currentTaskList.SelectedIndices)
_selectedIndicesCache.Add(i);
this.BeginInvoke(() => currentTaskList.Invalidate());
}
}
}
-206
View File
@@ -1,206 +0,0 @@
using System.Windows.Forms;
namespace StandardScene.Chained
{
partial class DeliveryViewer
{
/// <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();
}
if (disposing)
{
strip?.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()
{
this.components = new System.ComponentModel.Container();
this.currentTaskList = new System.Windows.Forms.ListView();
this.columnHeader8 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader9 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader7 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.label2 = new System.Windows.Forms.Label();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.checkBox1 = new System.Windows.Forms.CheckBox();
this.checkBox2 = new System.Windows.Forms.CheckBox();
this.SuspendLayout();
//
// currentTaskList
//
this.currentTaskList.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.currentTaskList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader8,
this.columnHeader1,
this.columnHeader4,
this.columnHeader5,
this.columnHeader9,
this.columnHeader6,
this.columnHeader2,
this.columnHeader7,
this.columnHeader3});
this.currentTaskList.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.currentTaskList.FullRowSelect = true;
this.currentTaskList.GridLines = true;
this.currentTaskList.HideSelection = false;
this.currentTaskList.Location = new System.Drawing.Point(38, 62);
this.currentTaskList.Name = "currentTaskList";
this.currentTaskList.Size = new System.Drawing.Size(1146, 429);
this.currentTaskList.TabIndex = 2;
this.currentTaskList.UseCompatibleStateImageBehavior = false;
this.currentTaskList.View = System.Windows.Forms.View.Details;
this.currentTaskList.VirtualMode = true;
this.currentTaskList.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.currentTaskList_RetrieveVirtualItem);
this.currentTaskList.SelectedIndexChanged += new System.EventHandler(this.currentTaskList_SelectedIndexChanged);
this.currentTaskList.MouseClick += new System.Windows.Forms.MouseEventHandler(this.currentTaskList_MouseClick);
//
// columnHeader8
//
this.columnHeader8.Text = "任务号";
this.columnHeader8.Width = 130;
//
// columnHeader1
//
this.columnHeader1.Text = "小车";
this.columnHeader1.Width = 100;
//
// columnHeader4
//
this.columnHeader4.Text = "取货点";
this.columnHeader4.Width = 130;
//
// columnHeader5
//
this.columnHeader5.Text = "放货点";
this.columnHeader5.Width = 130;
//
// columnHeader9
//
this.columnHeader9.Text = "任务状态";
this.columnHeader9.Width = 100;
//
// columnHeader6
//
this.columnHeader6.Text = "下发时间";
this.columnHeader6.Width = 130;
//
// columnHeader2
//
this.columnHeader2.Text = "执行时间";
this.columnHeader2.Width = 130;
//
// columnHeader7
//
this.columnHeader7.Text = "结束时间";
this.columnHeader7.Width = 130;
//
// columnHeader3
//
this.columnHeader3.Text = "优先级";
this.columnHeader3.Width = 83;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Font = new System.Drawing.Font("微软雅黑", 14.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.label2.Location = new System.Drawing.Point(33, 7);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(88, 26);
this.label2.TabIndex = 3;
this.label2.Text = "任务列表";
//
// timer1
//
this.timer1.Enabled = true;
this.timer1.Interval = 1000;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// checkBox1
//
this.checkBox1.AutoSize = true;
this.checkBox1.Checked = true;
this.checkBox1.CheckState = System.Windows.Forms.CheckState.Checked;
this.checkBox1.Location = new System.Drawing.Point(127, 15);
this.checkBox1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.checkBox1.Name = "checkBox1";
this.checkBox1.Size = new System.Drawing.Size(108, 16);
this.checkBox1.TabIndex = 4;
this.checkBox1.Text = "显示已完成任务";
this.checkBox1.UseVisualStyleBackColor = true;
//
// checkBox2
//
this.checkBox2.AutoSize = true;
this.checkBox2.Checked = true;
this.checkBox2.CheckState = System.Windows.Forms.CheckState.Checked;
this.checkBox2.Location = new System.Drawing.Point(239, 14);
this.checkBox2.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.checkBox2.Name = "checkBox2";
this.checkBox2.Size = new System.Drawing.Size(318, 16);
this.checkBox2.TabIndex = 5;
this.checkBox2.Text = "显示废止的任务(包括Error、Canceled、Terminated";
this.checkBox2.UseVisualStyleBackColor = true;
//
// DeliveryViewer
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1199, 551);
this.Controls.Add(this.checkBox2);
this.Controls.Add(this.checkBox1);
this.Controls.Add(this.label2);
this.Controls.Add(this.currentTaskList);
this.Name = "DeliveryViewer";
this.Text = "DeliveryViewer";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.DeliveryViewer_FormClosing);
this.Load += new System.EventHandler(this.DeliveryViewer_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label2;
private System.Windows.Forms.ColumnHeader columnHeader4;
private System.Windows.Forms.ColumnHeader columnHeader5;
private System.Windows.Forms.ColumnHeader columnHeader6;
private System.Windows.Forms.ColumnHeader columnHeader7;
private System.Windows.Forms.ColumnHeader columnHeader8;
private System.Windows.Forms.Timer timer1;
private System.Windows.Forms.ColumnHeader columnHeader1;
private System.Windows.Forms.ColumnHeader columnHeader2;
private System.Windows.Forms.ColumnHeader columnHeader9;
private System.Windows.Forms.CheckBox checkBox1;
private System.Windows.Forms.CheckBox checkBox2;
public System.Windows.Forms.ListView currentTaskList;
private System.Windows.Forms.ColumnHeader columnHeader3;
}
}
@@ -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="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>
-570
View File
@@ -1,570 +0,0 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace LoopViewerApp
{
partial class LoopViewer
{
private System.ComponentModel.IContainer components = null;
private ComboBox cmbTaskKind;
private NumericUpDown numCurrent;
private NumericUpDown numTarget;
private NumericUpDown numTraffic;
private CheckBox chkViaPoint;
private ComboBox cmbStartType;
private NumericUpDown numPriority;
private Button btnEdit; // 保留字段以供代码逻辑/样式使用(在界面上隐藏)
private Button btnDelete; // 保留字段以供代码逻辑/样式使用(在界面上隐藏)
private Button btnSave;
private Button btnCancel;
private ListView lstTasks;
private GroupBox grpEdit;
// 布局控件
private SplitContainer splitContainer;
private TableLayoutPanel tlpEdit;
private FlowLayoutPanel flpButtons;
// 中间竖向按钮(列表与编辑区之间)
private Panel pnlMiddle;
private FlowLayoutPanel flpMiddle;
private Button btnMiddleEdit;
private Button btnMiddleDelete;
// 列头
private ColumnHeader colId;
private ColumnHeader colTaskType;
private ColumnHeader colCurrent;
private ColumnHeader colTarget;
private ColumnHeader colTraffic;
private ColumnHeader colPriority;
private ColumnHeader colViaPoint;
private ColumnHeader colStartType;
// 标签字段(编辑区)
private Label lblKind;
private Label lblCurrent;
private Label lblTarget;
private Label lblTraffic;
private Label lblPriority;
private Label lblVia;
private Label lblStartType;
private Label lblEditingId; // 显示当前编辑的任务ID
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.splitContainer = new System.Windows.Forms.SplitContainer();
this.pnlMiddle = new System.Windows.Forms.Panel();
this.flpMiddle = new System.Windows.Forms.FlowLayoutPanel();
this.btnMiddleEdit = new System.Windows.Forms.Button();
this.btnMiddleDelete = new System.Windows.Forms.Button();
this.lstTasks = new System.Windows.Forms.ListView();
this.colId = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colTaskType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colCurrent = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colTarget = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colTraffic = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colPriority = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colViaPoint = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colStartType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.grpEdit = new System.Windows.Forms.GroupBox();
this.tlpEdit = new System.Windows.Forms.TableLayoutPanel();
this.lblEditingId = new System.Windows.Forms.Label();
this.lblKind = new System.Windows.Forms.Label();
this.cmbTaskKind = new System.Windows.Forms.ComboBox();
this.lblCurrent = new System.Windows.Forms.Label();
this.numCurrent = new System.Windows.Forms.NumericUpDown();
this.lblTarget = new System.Windows.Forms.Label();
this.numTarget = new System.Windows.Forms.NumericUpDown();
this.lblTraffic = new System.Windows.Forms.Label();
this.numTraffic = new System.Windows.Forms.NumericUpDown();
this.lblPriority = new System.Windows.Forms.Label();
this.numPriority = new System.Windows.Forms.NumericUpDown();
this.lblVia = new System.Windows.Forms.Label();
this.chkViaPoint = new System.Windows.Forms.CheckBox();
this.lblStartType = new System.Windows.Forms.Label();
this.cmbStartType = new System.Windows.Forms.ComboBox();
this.flpButtons = new System.Windows.Forms.FlowLayoutPanel();
this.btnSave = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.btnEdit = new System.Windows.Forms.Button();
this.btnDelete = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
this.splitContainer.Panel1.SuspendLayout();
this.splitContainer.Panel2.SuspendLayout();
this.splitContainer.SuspendLayout();
this.pnlMiddle.SuspendLayout();
this.flpMiddle.SuspendLayout();
this.grpEdit.SuspendLayout();
this.tlpEdit.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.numCurrent)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.numTarget)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.numTraffic)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.numPriority)).BeginInit();
this.flpButtons.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.pnlMiddle);
this.splitContainer.Panel1.Controls.Add(this.lstTasks);
//
// splitContainer.Panel2
//
this.splitContainer.Panel2.Controls.Add(this.grpEdit);
this.splitContainer.Size = new System.Drawing.Size(1200, 600);
this.splitContainer.SplitterDistance = 680;
this.splitContainer.SplitterWidth = 6;
this.splitContainer.TabIndex = 0;
//
// pnlMiddle
//
this.pnlMiddle.Controls.Add(this.flpMiddle);
this.pnlMiddle.Dock = System.Windows.Forms.DockStyle.Right;
this.pnlMiddle.Location = new System.Drawing.Point(614, 0);
this.pnlMiddle.Name = "pnlMiddle";
this.pnlMiddle.Padding = new System.Windows.Forms.Padding(6);
this.pnlMiddle.Size = new System.Drawing.Size(66, 600);
this.pnlMiddle.TabIndex = 0;
//
// flpMiddle
//
this.flpMiddle.Anchor = System.Windows.Forms.AnchorStyles.None;
this.flpMiddle.Controls.Add(this.btnMiddleEdit);
this.flpMiddle.Controls.Add(this.btnMiddleDelete);
this.flpMiddle.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
this.flpMiddle.Location = new System.Drawing.Point(0, 220);
this.flpMiddle.Name = "flpMiddle";
this.flpMiddle.Padding = new System.Windows.Forms.Padding(2);
this.flpMiddle.Size = new System.Drawing.Size(63, 160);
this.flpMiddle.TabIndex = 0;
this.flpMiddle.WrapContents = false;
//
// btnMiddleEdit
//
this.btnMiddleEdit.BackColor = System.Drawing.SystemColors.Control;
this.btnMiddleEdit.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnMiddleEdit.Font = new System.Drawing.Font("微软雅黑", 9F);
this.btnMiddleEdit.Location = new System.Drawing.Point(6, 12);
this.btnMiddleEdit.Margin = new System.Windows.Forms.Padding(4, 10, 4, 4);
this.btnMiddleEdit.Name = "btnMiddleEdit";
this.btnMiddleEdit.Size = new System.Drawing.Size(50, 40);
this.btnMiddleEdit.TabIndex = 0;
this.btnMiddleEdit.Text = "编辑";
this.btnMiddleEdit.UseVisualStyleBackColor = false;
this.btnMiddleEdit.Click += new System.EventHandler(this.btnEdit_Click);
//
// btnMiddleDelete
//
this.btnMiddleDelete.BackColor = System.Drawing.Color.LightCoral;
this.btnMiddleDelete.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnMiddleDelete.Font = new System.Drawing.Font("微软雅黑", 9F);
this.btnMiddleDelete.Location = new System.Drawing.Point(6, 62);
this.btnMiddleDelete.Margin = new System.Windows.Forms.Padding(4, 6, 4, 4);
this.btnMiddleDelete.Name = "btnMiddleDelete";
this.btnMiddleDelete.Size = new System.Drawing.Size(50, 40);
this.btnMiddleDelete.TabIndex = 1;
this.btnMiddleDelete.Text = "删除";
this.btnMiddleDelete.UseVisualStyleBackColor = false;
this.btnMiddleDelete.Click += new System.EventHandler(this.btnDelete_Click);
//
// lstTasks
//
this.lstTasks.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.colId,
this.colTaskType,
this.colCurrent,
this.colTarget,
this.colTraffic,
this.colPriority,
this.colViaPoint,
this.colStartType});
this.lstTasks.Dock = System.Windows.Forms.DockStyle.Fill;
this.lstTasks.FullRowSelect = true;
this.lstTasks.HideSelection = false;
this.lstTasks.Location = new System.Drawing.Point(0, 0);
this.lstTasks.Name = "lstTasks";
this.lstTasks.OwnerDraw = true;
this.lstTasks.Size = new System.Drawing.Size(680, 600);
this.lstTasks.TabIndex = 0;
this.lstTasks.UseCompatibleStateImageBehavior = false;
this.lstTasks.View = System.Windows.Forms.View.Details;
this.lstTasks.DrawColumnHeader += new System.Windows.Forms.DrawListViewColumnHeaderEventHandler(this.lstTasks_DrawColumnHeader);
this.lstTasks.DrawItem += new System.Windows.Forms.DrawListViewItemEventHandler(this.lstTasks_DrawItem);
this.lstTasks.DrawSubItem += new System.Windows.Forms.DrawListViewSubItemEventHandler(this.lstTasks_DrawSubItem);
this.lstTasks.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.lstTasks_MouseDoubleClick);
//
// colId
//
this.colId.Text = "ID";
this.colId.Width = 40;
//
// colTaskType
//
this.colTaskType.Text = "任务类别";
this.colTaskType.Width = 110;
//
// colCurrent
//
this.colCurrent.Text = "当前站点";
this.colCurrent.Width = 90;
//
// colTarget
//
this.colTarget.Text = "目标站点";
this.colTarget.Width = 90;
//
// colTraffic
//
this.colTraffic.Text = "流量控制";
this.colTraffic.Width = 90;
//
// colPriority
//
this.colPriority.Text = "优先级";
this.colPriority.Width = 80;
//
// colViaPoint
//
this.colViaPoint.Text = "途径点";
this.colViaPoint.Width = 70;
//
// colStartType
//
this.colStartType.Text = "启动类型";
this.colStartType.Width = 100;
//
// grpEdit
//
this.grpEdit.Controls.Add(this.tlpEdit);
this.grpEdit.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpEdit.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.grpEdit.Location = new System.Drawing.Point(0, 0);
this.grpEdit.Name = "grpEdit";
this.grpEdit.Size = new System.Drawing.Size(514, 600);
this.grpEdit.TabIndex = 1;
this.grpEdit.TabStop = false;
this.grpEdit.Text = "任务信息(选中列表项后可编辑)";
//
// tlpEdit
//
this.tlpEdit.ColumnCount = 2;
this.tlpEdit.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 120F));
this.tlpEdit.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpEdit.Controls.Add(this.lblEditingId, 0, 0);
this.tlpEdit.Controls.Add(this.lblKind, 0, 1);
this.tlpEdit.Controls.Add(this.cmbTaskKind, 1, 1);
this.tlpEdit.Controls.Add(this.lblCurrent, 0, 2);
this.tlpEdit.Controls.Add(this.numCurrent, 1, 2);
this.tlpEdit.Controls.Add(this.lblTarget, 0, 3);
this.tlpEdit.Controls.Add(this.numTarget, 1, 3);
this.tlpEdit.Controls.Add(this.lblTraffic, 0, 4);
this.tlpEdit.Controls.Add(this.numTraffic, 1, 4);
this.tlpEdit.Controls.Add(this.lblPriority, 0, 5);
this.tlpEdit.Controls.Add(this.numPriority, 1, 5);
this.tlpEdit.Controls.Add(this.lblVia, 0, 6);
this.tlpEdit.Controls.Add(this.chkViaPoint, 1, 6);
this.tlpEdit.Controls.Add(this.lblStartType, 0, 7);
this.tlpEdit.Controls.Add(this.cmbStartType, 1, 7);
this.tlpEdit.Controls.Add(this.flpButtons, 1, 8);
this.tlpEdit.Dock = System.Windows.Forms.DockStyle.Fill;
this.tlpEdit.Location = new System.Drawing.Point(3, 25);
this.tlpEdit.Name = "tlpEdit";
this.tlpEdit.Padding = new System.Windows.Forms.Padding(8);
this.tlpEdit.RowCount = 9;
this.tlpEdit.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 36F));
this.tlpEdit.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 36F));
this.tlpEdit.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 36F));
this.tlpEdit.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 36F));
this.tlpEdit.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 36F));
this.tlpEdit.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 36F));
this.tlpEdit.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 36F));
this.tlpEdit.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 36F));
this.tlpEdit.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpEdit.Size = new System.Drawing.Size(508, 572);
this.tlpEdit.TabIndex = 0;
//
// lblEditingId
//
this.lblEditingId.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblEditingId.AutoSize = true;
this.tlpEdit.SetColumnSpan(this.lblEditingId, 2);
this.lblEditingId.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.lblEditingId.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(120)))), ((int)(((byte)(215)))));
this.lblEditingId.Location = new System.Drawing.Point(11, 14);
this.lblEditingId.Name = "lblEditingId";
this.lblEditingId.Size = new System.Drawing.Size(78, 24);
this.lblEditingId.TabIndex = 0;
this.lblEditingId.Text = "新增任务";
//
// lblKind
//
this.lblKind.Dock = System.Windows.Forms.DockStyle.Fill;
this.lblKind.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lblKind.Location = new System.Drawing.Point(11, 44);
this.lblKind.Name = "lblKind";
this.lblKind.Size = new System.Drawing.Size(114, 36);
this.lblKind.TabIndex = 1;
this.lblKind.Text = "任务类别:";
this.lblKind.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// cmbTaskKind
//
this.cmbTaskKind.Dock = System.Windows.Forms.DockStyle.Fill;
this.cmbTaskKind.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cmbTaskKind.Font = new System.Drawing.Font("微软雅黑", 10F);
this.cmbTaskKind.Items.AddRange(new object[] {
"Loop",
"BranchPoint",
"JoinPoint"});
this.cmbTaskKind.Location = new System.Drawing.Point(131, 47);
this.cmbTaskKind.Name = "cmbTaskKind";
this.cmbTaskKind.Size = new System.Drawing.Size(366, 31);
this.cmbTaskKind.TabIndex = 2;
//
// lblCurrent
//
this.lblCurrent.Dock = System.Windows.Forms.DockStyle.Fill;
this.lblCurrent.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lblCurrent.Location = new System.Drawing.Point(11, 80);
this.lblCurrent.Name = "lblCurrent";
this.lblCurrent.Size = new System.Drawing.Size(114, 36);
this.lblCurrent.TabIndex = 3;
this.lblCurrent.Text = "当前站点:";
this.lblCurrent.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// numCurrent
//
this.numCurrent.Dock = System.Windows.Forms.DockStyle.Left;
this.numCurrent.Font = new System.Drawing.Font("微软雅黑", 10F);
this.numCurrent.Location = new System.Drawing.Point(131, 83);
this.numCurrent.Maximum = new decimal(new int[] {
1000000,
0,
0,
0});
this.numCurrent.Name = "numCurrent";
this.numCurrent.Size = new System.Drawing.Size(120, 29);
this.numCurrent.TabIndex = 4;
//
// lblTarget
//
this.lblTarget.Dock = System.Windows.Forms.DockStyle.Fill;
this.lblTarget.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lblTarget.Location = new System.Drawing.Point(11, 116);
this.lblTarget.Name = "lblTarget";
this.lblTarget.Size = new System.Drawing.Size(114, 36);
this.lblTarget.TabIndex = 5;
this.lblTarget.Text = "目标站点:";
this.lblTarget.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// numTarget
//
this.numTarget.Dock = System.Windows.Forms.DockStyle.Left;
this.numTarget.Font = new System.Drawing.Font("微软雅黑", 10F);
this.numTarget.Location = new System.Drawing.Point(131, 119);
this.numTarget.Maximum = new decimal(new int[] {
1000000,
0,
0,
0});
this.numTarget.Name = "numTarget";
this.numTarget.Size = new System.Drawing.Size(120, 29);
this.numTarget.TabIndex = 6;
//
// lblTraffic
//
this.lblTraffic.Dock = System.Windows.Forms.DockStyle.Fill;
this.lblTraffic.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lblTraffic.Location = new System.Drawing.Point(11, 152);
this.lblTraffic.Name = "lblTraffic";
this.lblTraffic.Size = new System.Drawing.Size(114, 36);
this.lblTraffic.TabIndex = 7;
this.lblTraffic.Text = "流量控制:";
this.lblTraffic.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// numTraffic
//
this.numTraffic.Dock = System.Windows.Forms.DockStyle.Left;
this.numTraffic.Font = new System.Drawing.Font("微软雅黑", 10F);
this.numTraffic.Location = new System.Drawing.Point(131, 155);
this.numTraffic.Maximum = new decimal(new int[] {
1000,
0,
0,
0});
this.numTraffic.Name = "numTraffic";
this.numTraffic.Size = new System.Drawing.Size(120, 29);
this.numTraffic.TabIndex = 8;
//
// lblPriority
//
this.lblPriority.Dock = System.Windows.Forms.DockStyle.Fill;
this.lblPriority.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lblPriority.Location = new System.Drawing.Point(11, 188);
this.lblPriority.Name = "lblPriority";
this.lblPriority.Size = new System.Drawing.Size(114, 36);
this.lblPriority.TabIndex = 9;
this.lblPriority.Text = "优先级:";
this.lblPriority.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// numPriority
//
this.numPriority.Dock = System.Windows.Forms.DockStyle.Left;
this.numPriority.Font = new System.Drawing.Font("微软雅黑", 10F);
this.numPriority.Location = new System.Drawing.Point(131, 191);
this.numPriority.Name = "numPriority";
this.numPriority.Size = new System.Drawing.Size(120, 29);
this.numPriority.TabIndex = 10;
this.numPriority.Value = new decimal(new int[] {
1,
0,
0,
0});
//
// lblVia
//
this.lblVia.Dock = System.Windows.Forms.DockStyle.Fill;
this.lblVia.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lblVia.Location = new System.Drawing.Point(11, 224);
this.lblVia.Name = "lblVia";
this.lblVia.Size = new System.Drawing.Size(114, 36);
this.lblVia.TabIndex = 11;
this.lblVia.Text = "途径点:";
this.lblVia.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// chkViaPoint
//
this.chkViaPoint.Dock = System.Windows.Forms.DockStyle.Left;
this.chkViaPoint.Font = new System.Drawing.Font("微软雅黑", 10F);
this.chkViaPoint.Location = new System.Drawing.Point(131, 227);
this.chkViaPoint.Name = "chkViaPoint";
this.chkViaPoint.Size = new System.Drawing.Size(104, 30);
this.chkViaPoint.TabIndex = 12;
this.chkViaPoint.Text = "是";
//
// lblStartType
//
this.lblStartType.Dock = System.Windows.Forms.DockStyle.Fill;
this.lblStartType.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lblStartType.Location = new System.Drawing.Point(11, 260);
this.lblStartType.Name = "lblStartType";
this.lblStartType.Size = new System.Drawing.Size(114, 36);
this.lblStartType.TabIndex = 13;
this.lblStartType.Text = "启动类型:";
this.lblStartType.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// cmbStartType
//
this.cmbStartType.Dock = System.Windows.Forms.DockStyle.Fill;
this.cmbStartType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cmbStartType.Font = new System.Drawing.Font("微软雅黑", 10F);
this.cmbStartType.Items.AddRange(new object[] {
"Api",
"Plc",
"ButtonBox",
"AutoLoop",
"Charge"});
this.cmbStartType.Location = new System.Drawing.Point(131, 263);
this.cmbStartType.Name = "cmbStartType";
this.cmbStartType.Size = new System.Drawing.Size(366, 31);
this.cmbStartType.TabIndex = 14;
//
// flpButtons
//
this.flpButtons.AutoSize = true;
this.flpButtons.Controls.Add(this.btnSave);
this.flpButtons.Controls.Add(this.btnCancel);
this.flpButtons.Dock = System.Windows.Forms.DockStyle.Left;
this.flpButtons.Location = new System.Drawing.Point(131, 299);
this.flpButtons.Name = "flpButtons";
this.flpButtons.Size = new System.Drawing.Size(292, 262);
this.flpButtons.TabIndex = 15;
//
// btnSave
//
this.btnSave.BackColor = System.Drawing.Color.LightBlue;
this.btnSave.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnSave.Font = new System.Drawing.Font("微软雅黑", 11F, System.Drawing.FontStyle.Bold);
this.btnSave.Location = new System.Drawing.Point(3, 3);
this.btnSave.Name = "btnSave";
this.btnSave.Size = new System.Drawing.Size(140, 40);
this.btnSave.TabIndex = 0;
this.btnSave.Text = "保存";
this.btnSave.UseVisualStyleBackColor = false;
this.btnSave.Click += new System.EventHandler(this.btnSave_Click);
//
// btnCancel
//
this.btnCancel.BackColor = System.Drawing.SystemColors.Control;
this.btnCancel.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnCancel.Font = new System.Drawing.Font("微软雅黑", 11F);
this.btnCancel.Location = new System.Drawing.Point(149, 3);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(140, 40);
this.btnCancel.TabIndex = 1;
this.btnCancel.Text = "取消";
this.btnCancel.UseVisualStyleBackColor = false;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// btnEdit
//
this.btnEdit.Location = new System.Drawing.Point(0, 0);
this.btnEdit.Name = "btnEdit";
this.btnEdit.Size = new System.Drawing.Size(75, 23);
this.btnEdit.TabIndex = 0;
this.btnEdit.Visible = false;
//
// btnDelete
//
this.btnDelete.Location = new System.Drawing.Point(0, 0);
this.btnDelete.Name = "btnDelete";
this.btnDelete.Size = new System.Drawing.Size(75, 23);
this.btnDelete.TabIndex = 0;
this.btnDelete.Visible = false;
//
// LoopViewer
//
this.ClientSize = new System.Drawing.Size(1200, 600);
this.Controls.Add(this.splitContainer);
this.Font = new System.Drawing.Font("微软雅黑", 9F);
this.MinimumSize = new System.Drawing.Size(1000, 420);
this.Name = "LoopViewer";
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.pnlMiddle.ResumeLayout(false);
this.flpMiddle.ResumeLayout(false);
this.grpEdit.ResumeLayout(false);
this.tlpEdit.ResumeLayout(false);
this.tlpEdit.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.numCurrent)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.numTarget)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.numTraffic)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.numPriority)).EndInit();
this.flpButtons.ResumeLayout(false);
this.ResumeLayout(false);
}
}
}
+278 -534
View File
@@ -1,595 +1,339 @@
using Newtonsoft.Json;
using StandardScene.Model;
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using System.Threading.Tasks;
using CycleGUI;
using Newtonsoft.Json;
using SimpleCore.Library;
using StandardScene.Model;
using StandardScene.Utils;
namespace LoopViewerApp
{
public partial class LoopViewer : Form
/// <summary>
/// 环线/循环任务配置管理界面(CycleGUI 版,替代原 WinForms <c>LoopViewer</c> 窗体)。
/// <list type="bullet">
/// <item>维护 <c>tasklist.json</c><see cref="List{T}"/> of <see cref="LoopTask"/>)的增 / 改 / 删;与 <c>AbstractLoopMission</c> 读取同一文件。</item>
/// <item>单实例:再次打开则把已有面板置前。</item>
/// <item>勾选多行后「删除选中」可批量删除(保留原 ListView 多选删除能力);每行「编辑」按钮打开编辑对话框。</item>
/// <item>文件写入放后台线程,绝不阻塞渲染线程(避免界面卡死)。</item>
/// </list>
/// 沿用 <c>DeliveryViewer</c> 的同套模式(单实例面板、<c>pb.Table</c>、<c>CycleUiHelper.ConfirmThen</c>),不另造轮子。
/// 保留可实例化 + <see cref="Show"/> 以兼容既有调用 <c>new LoopViewer().Show()</c>。
/// </summary>
public class LoopViewer
{
private readonly string jsonPath =
Path.Combine(Application.StartupPath, "tasklist.json");
private const string TableId = "loop-task-list";
private List<LoopTask> tasks = new List<LoopTask>();
// 与 AbstractLoopMission 完全一致的读取路径,保证“写哪儿、它就读哪儿”。
private static string JsonPath => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "tasklist.json");
// -1 表示新增模式;>=0 表示正在编辑对应索引
private int editingIndex = -1;
private static readonly object SaveLock = new object();
// 直接取自枚举,自动与 TaskKind / TaskStartType 保持同步(含 Charge),无需手写列表。
private static readonly string[] KindNames = Enum.GetNames(typeof(TaskKind));
private static readonly string[] StartTypeNames = Enum.GetNames(typeof(TaskStartType));
public LoopViewer()
private static Panel _panel;
private static Panel _dialog; // 新增/编辑对话框,限单实例
private static List<LoopTask> _tasks = new List<LoopTask>(); // 仅渲染线程读写
private static readonly HashSet<int> _selected = new HashSet<int>(); // 仅渲染线程读写,存被勾选任务的 Id
private static volatile string _status = "";
/// <summary>打开(或置前)任务管理面板。兼容原 <c>new LoopViewer().Show()</c> 调用方式。</summary>
public void Show() => Open();
/// <summary>打开(或置前)任务管理面板。</summary>
public static void Open()
{
InitializeComponent();
if (_panel != null)
{
try
{
_panel.BringToFront();
return;
}
catch
{
_panel = null;
}
}
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
_selected.Clear();
LoadTasks();
var panel = GUI.DeclarePanel()
.ShowTitle("任务列表管理器")
.SetDefaultDocking(Panel.Docking.None)
.InitSize(1080, 620)
.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;
}
if (pb.Button("新增任务", distinct: "loop-add"))
OpenEditDialog(null);
pb.SameLine(12);
if (pb.Button("删除选中", distinct: "loop-del-selected"))
ConfirmDeleteSelected();
pb.SameLine(16);
pb.Label($"共 {_tasks.Count} 个任务,已选 {_selected.Count} 个");
pb.Table(TableId,
new[] { "选择", "ID", "任务类别", "当前站点", "目标站点", "流量控制", "优先级", "途径点", "启动类型", "操作" },
_tasks.Count, (row, i) =>
{
var t = _tasks[i];
var id = t.Id;
var sel = _selected.Contains(id);
if (row.Checkbox(ref sel, "勾选以批量删除"))
{
if (sel) _selected.Add(id);
else _selected.Remove(id);
}
row.Label($"{t.Id}");
row.Label($"{t.Kind}");
row.Label($"{t.CurrentStationId}");
row.Label($"{t.TargetStationId}");
row.Label($"{t.TrafficControl}");
row.Label($"{t.Priority}");
row.Label(t.IsViaPoint ? "是" : "否");
row.Label($"{t.StartType}");
if (row.ButtonGroup(new[] { "编辑" }, new[] { "编辑该任务" }) == 0)
OpenEditDialog(t);
}, height: 18, enableSearch: true);
if (!string.IsNullOrEmpty(_status))
{
pb.Separator();
pb.Label(_status);
}
// 事件驱动为主,配合较慢的节流重绘即可保证后台保存结果/状态及时反映。
pb.Panel.Repaint(repaintTimeMs: 500);
});
}
/// <summary>对选中项发起二次确认后删除(保留原多选删除的提示文案)。</summary>
private static void ConfirmDeleteSelected()
{
if (_selected.Count == 0)
{
_status = "未选择任何任务";
_panel?.Repaint();
return;
// 应用 ChargeStationManagementForm 风格的运行时样式调整
ApplyChargeStyle();
EnsureComboItems();
// 启用多选并绑定右键菜单与 Delete 键删除功能
try
{
if (lstTasks != null)
{
lstTasks.MultiSelect = true;
// 右键菜单:删除
var ctx = new ContextMenuStrip();
ctx.Items.Add("删除", null, (s, e) => OnDeleteSelectedTasks());
lstTasks.ContextMenuStrip = ctx;
// 键盘删除键绑定
lstTasks.KeyDown += lstTasks_KeyDown;
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"LoopViewer context menu init error: {ex}");
}
try
{
InitOrLoadJson();
RenderListView();
UpdateSaveButtonText();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"LoopViewer initialization error: {ex}");
}
string prompt;
if (_selected.Count == 1)
prompt = $"确认删除任务 ID={_selected.First()}";
else
prompt = $"确认删除所选 {_selected.Count} 个任务?";
// 删除仅做内存列表增删(极快,可在渲染线程执行);真正的文件写入在 SaveTasks 内部放后台线程。
CycleUiHelper.ConfirmThen(prompt, DeleteSelected);
}
private void lstTasks_KeyDown(object sender, KeyEventArgs e)
private static void DeleteSelected()
{
try
{
if (e.KeyCode == Keys.Delete)
{
OnDeleteSelectedTasks();
e.Handled = true;
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"lstTasks_KeyDown error: {ex}");
}
var removed = _tasks.RemoveAll(t => _selected.Contains(t.Id));
_selected.Clear();
SaveTasks();
_status = $"已删除 {removed} 个任务";
_panel?.Repaint();
}
/// <summary>
/// 删除 ListView 中选中的任务(支持多选)
/// 打开「新增 / 编辑」对话框(置顶非模态、限单实例)。<paramref name="existing"/> 为 null 表示新增,否则编辑该任务(保留其 Id)。
/// 每次打开都是全新面板:<c>defaultText</c> 能正确初始化,规避立即模式下文本框缓冲难以重置的问题。
/// </summary>
private void OnDeleteSelectedTasks()
private static void OpenEditDialog(LoopTask existing)
{
try
if (_dialog != null)
{
if (lstTasks == null || lstTasks.SelectedIndices.Count == 0)
try { _dialog.BringToFront(); return; }
catch { _dialog = null; }
}
bool isAdd = existing == null;
int kindIdx = isAdd ? 0 : Math.Max(0, Array.IndexOf(KindNames, existing.Kind.ToString()));
int startIdx = Math.Max(0, Array.IndexOf(StartTypeNames,
(isAdd ? TaskStartType.AutoLoop : existing.StartType).ToString()));
string curText = (isAdd ? 0 : Clamp(existing.CurrentStationId, 0, 1000000)).ToString();
string tgtText = (isAdd ? 0 : Clamp(existing.TargetStationId, 0, 1000000)).ToString();
string trafficText = (isAdd ? 0 : Clamp(existing.TrafficControl, 0, 1000)).ToString();
string priText = (isAdd ? 1 : Clamp(existing.Priority, 0, 100)).ToString();
bool via = !isAdd && existing.IsViaPoint;
string err = "";
// 不用 Modal:原生「模态弹窗 + 标题栏关闭X」的 EndPopup 配对 bug 会断言崩溃。
// 也不用 TopMost:置顶视口带 NoAutoMerge,会让 DropdownBox 的下拉弹窗落到独立非置顶视口里、被对话框挡在后面(看不到选项)。
// 故采用与 DeliveryViewer 相同的普通浮动面板(非模态、不停靠):Begin/End 路径,X 关闭干净,下拉弹窗 z 序正常。
var dlg = GUI.DeclarePanel()
.ShowTitle(isAdd ? "新增任务" : $"编辑任务 ID: {existing.Id}")
.SetDefaultDocking(Panel.Docking.None)
.InitSize(420, 380)
.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;
// 收集被选中的索引并按降序删除,避免索引移动问题
var selectedIndices = lstTasks.SelectedIndices.Cast<int>().OrderByDescending(i => i).ToList();
// 构造确认提示
string prompt;
if (selectedIndices.Count == 1)
{
int idx = selectedIndices[0];
if (idx >= 0 && idx < tasks.Count)
prompt = $"确认删除任务 ID={tasks[idx].Id}";
else
prompt = "确认删除选中任务?";
}
else
{
prompt = $"确认删除所选 {selectedIndices.Count} 个任务?";
}
if (MessageBox.Show(prompt, "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
return;
// 控件 id 由 ImHashStr(prompt) 经 Encoding.ASCII 计算:中文会被压成 '?',导致同字数纯中文标签
// (如“当前站点/目标站点”“任务类别/启动类型”)哈希相同而抛 Duplicated id。故各标签加唯一 ASCII 序号前缀以区分。
pb.DropdownBox("1. 任务类别", KindNames, ref kindIdx);
var (c, _) = pb.TextInput("2. 当前站点 (0~1000000)", curText, alwaysReturnString: true);
curText = c;
var (tg, _) = pb.TextInput("3. 目标站点 (0~1000000)", tgtText, alwaysReturnString: true);
tgtText = tg;
var (tf, _) = pb.TextInput("4. 流量控制 (0~1000)", trafficText, alwaysReturnString: true);
trafficText = tf;
var (pr, _) = pb.TextInput("5. 优先级 (0~100)", priText, alwaysReturnString: true);
priText = pr;
pb.CheckBox("6. 途径点", ref via);
pb.DropdownBox("7. 启动类型", StartTypeNames, ref startIdx);
// 删除任务
foreach (var idx in selectedIndices)
if (!string.IsNullOrEmpty(err))
{
if (idx >= 0 && idx < tasks.Count)
pb.Separator();
pb.Label(err);
}
pb.Separator();
if (pb.Button("保存", distinct: "loop-edit-save"))
{
if (!TryParseClamp(curText, 0, 1000000, out var cur)) { err = "当前站点需为 0~1000000 的整数"; return; }
if (!TryParseClamp(tgtText, 0, 1000000, out var tgt)) { err = "目标站点需为 0~1000000 的整数"; return; }
if (!TryParseClamp(trafficText, 0, 1000, out var traffic)) { err = "流量控制需为 0~1000 的整数"; return; }
if (!TryParseClamp(priText, 0, 100, out var pri)) { err = "优先级需为 0~100 的整数"; return; }
Enum.TryParse<TaskKind>(KindNames[kindIdx], out var kind);
Enum.TryParse<TaskStartType>(StartTypeNames[startIdx], out var st);
if (isAdd)
{
tasks.RemoveAt(idx);
}
}
// 如果被删除项包含当前正在编辑的项,退出编辑状态
if (editingIndex >= 0)
{
if (editingIndex >= tasks.Count || selectedIndices.Any(i => i == editingIndex))
{
editingIndex = -1;
UpdateSaveButtonText();
ClearPanelInputs();
_tasks.Add(new LoopTask
{
Id = GetNextTaskId(),
Kind = kind,
CurrentStationId = cur,
TargetStationId = tgt,
TrafficControl = traffic,
Priority = pri,
IsViaPoint = via,
StartType = st
});
_status = "已新增任务";
}
else
{
// 重新计算编辑索引在删除后的新位置
int removedBefore = selectedIndices.Count(i => i < editingIndex);
editingIndex -= removedBefore;
existing.Kind = kind;
existing.CurrentStationId = cur;
existing.TargetStationId = tgt;
existing.TrafficControl = traffic;
existing.Priority = pri;
existing.IsViaPoint = via;
existing.StartType = st;
_status = $"已保存任务 ID={existing.Id}";
}
}
// 持久化并刷新列表视图
Save();
RenderListView();
SaveTasks();
dlg.Exit();
_dialog = null;
_panel?.Repaint();
}
pb.SameLine(8);
if (pb.Button("取消", distinct: "loop-edit-cancel"))
{
dlg.Exit();
_dialog = null;
}
});
}
/// <summary>下一个可用任务 Id(当前最大 Id + 1,空表则为 1)。</summary>
private static int GetNextTaskId() => _tasks.Count == 0 ? 1 : _tasks.Max(t => t.Id) + 1;
private static void LoadTasks()
{
try
{
var path = JsonPath;
if (!File.Exists(path))
File.WriteAllText(path, "[]");
var text = File.ReadAllText(path);
_tasks = JsonConvert.DeserializeObject<List<LoopTask>>(text) ?? new List<LoopTask>();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"OnDeleteSelectedTasks error: {ex}");
MessageBox.Show("删除失败:" + ex.Message);
_tasks = new List<LoopTask>();
_status = "加载 tasklist.json 失败,详见日志";
Diagnosis.Post($"LoopViewer 加载 tasklist.json 异常: {ExceptionFormatter.FormatEx(ex)}");
}
}
/// <summary>
/// 将 LoopViewer 的运行时样式调整为与 ChargeStationManagementForm 接近的视觉风格:
/// - 全局字体设为微软雅黑
/// - 表头暖色替换为蓝色沉稳风格(和充电界面一致)
/// - 按钮字号、背景色与充电界面保持一致(保存/删除/取消)
/// - 列表视图设置为整行选择、无边框、交替背景等
/// 注意:不修改 Designer 文件,仅在运行时统一控件表现,避免破坏设计器生成代码。
/// </summary>
private void ApplyChargeStyle()
/// <summary>序列化在渲染线程完成(极快),文件写入放后台线程,避免阻塞渲染线程。</summary>
private static void SaveTasks()
{
string json;
try
{
// 窗体级设置
this.StartPosition = FormStartPosition.CenterScreen;
this.MinimumSize = new System.Drawing.Size(1327, 738);
this.Font = new Font("微软雅黑", 9F, FontStyle.Regular);
// 调整 ListView(如果存在)
if (lstTasks != null)
{
lstTasks.View = View.Details;
lstTasks.FullRowSelect = true;
lstTasks.GridLines = false;
lstTasks.HeaderStyle = ColumnHeaderStyle.Nonclickable;
lstTasks.OwnerDraw = true; // 已有自定义绘制
lstTasks.BackColor = Color.White;
lstTasks.ForeColor = Color.FromArgb(33, 33, 33);
// 多选由初始化时控制(这里不强制)
}
// 下拉框统一字体
if (cmbTaskKind != null) cmbTaskKind.Font = new Font("微软雅黑", 10F, FontStyle.Regular);
if (cmbStartType != null) cmbStartType.Font = new Font("微软雅黑", 10F, FontStyle.Regular);
// 数值输入框统一字体
if (numCurrent != null) numCurrent.Font = new Font("微软雅黑", 10F, FontStyle.Regular);
if (numTarget != null) numTarget.Font = new Font("微软雅黑", 10F, FontStyle.Regular);
if (numTraffic != null) numTraffic.Font = new Font("微软雅黑", 10F, FontStyle.Regular);
if (numPriority != null) numPriority.Font = new Font("微软雅黑", 10F, FontStyle.Regular);
// 标签字体统一
if (lblEditingId != null) lblEditingId.Font = new Font("微软雅黑", 10F, FontStyle.Bold);
// 按钮风格:与 ChargeStationManagementForm 保持一致的视觉优先级
if (btnSave != null)
{
btnSave.BackColor = Color.LightBlue;
btnSave.ForeColor = Color.Black;
btnSave.Font = new Font("微软雅黑", 11F, FontStyle.Bold);
btnSave.FlatStyle = FlatStyle.Flat;
}
if (btnDelete != null)
{
btnDelete.BackColor = Color.LightCoral;
btnDelete.ForeColor = Color.Black;
btnDelete.Font = new Font("微软雅黑", 11F, FontStyle.Bold);
btnDelete.FlatStyle = FlatStyle.Flat;
}
if (btnCancel != null)
{
btnCancel.BackColor = SystemColors.Control;
btnCancel.ForeColor = Color.Black;
btnCancel.Font = new Font("微软雅黑", 11F, FontStyle.Regular);
btnCancel.FlatStyle = FlatStyle.Flat;
}
// 如果存在额外的操作按钮(例如在面板上),尝试统一风格(容错)
foreach (Control ctrl in this.Controls)
{
if (ctrl is Panel pnl)
{
pnl.Padding = new Padding(12);
}
else if (ctrl is Button btn)
{
// 已设置主要按钮,其他按钮使用中性风格
if (btn == btnSave || btn == btnDelete || btn == btnCancel) continue;
btn.Font = new Font("微软雅黑", 10F, FontStyle.Regular);
}
}
json = JsonConvert.SerializeObject(_tasks, Formatting.Indented);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"ApplyChargeStyle error: {ex}");
_status = "保存失败,详见日志";
Diagnosis.Post($"LoopViewer 序列化 tasklist.json 异常: {ExceptionFormatter.FormatEx(ex)}");
return;
}
}
private void EnsureComboItems()
{
try
var path = JsonPath;
Task.Run(() =>
{
if (cmbTaskKind != null && cmbTaskKind.Items.Count == 0)
try
{
cmbTaskKind.Items.AddRange(new object[] { "Loop", "BranchPoint", "JoinPoint" });
cmbTaskKind.SelectedIndex = 0;
lock (SaveLock)
File.WriteAllText(path, json);
}
if (cmbStartType != null && cmbStartType.Items.Count == 0)
catch (Exception ex)
{
cmbStartType.Items.AddRange(new object[] { "Api", "Plc", "ButtonBox", "AutoLoop" });
cmbStartType.SelectedIndex = 3;
_status = "保存失败,详见日志";
Diagnosis.Post($"LoopViewer 保存 tasklist.json 异常: {ExceptionFormatter.FormatEx(ex)}");
_panel?.Repaint();
}
// 确保下拉框字体一致(防止 Designer 未设置)
if (cmbTaskKind != null) cmbTaskKind.Font = new Font("微软雅黑", 10F, FontStyle.Regular);
if (cmbStartType != null) cmbStartType.Font = new Font("微软雅黑", 10F, FontStyle.Regular);
}
catch { }
});
}
#region /
private void InitOrLoadJson()
private static int Clamp(int v, int min, int max) => v < min ? min : (v > max ? max : v);
private static bool TryParseClamp(string s, int min, int max, out int value)
{
try
if (int.TryParse((s ?? "").Trim(), out value))
{
if (!File.Exists(jsonPath))
File.WriteAllText(jsonPath, "[]");
var text = File.ReadAllText(jsonPath);
tasks = JsonConvert.DeserializeObject<List<LoopTask>>(text) ?? new List<LoopTask>();
}
catch (Exception ex)
{
tasks = new List<LoopTask>();
System.Diagnostics.Debug.WriteLine($"Load tasks failed: {ex}");
value = Clamp(value, min, max);
return true;
}
value = min;
return false;
}
#endregion
#region ID
/// <summary>
/// 获取下一个可用的任务ID(当前最大ID + 1)
/// </summary>
/// <returns>新的任务ID</returns>
private int GetNextTaskId()
{
if (tasks == null || tasks.Count == 0)
return 1;
int maxId = tasks.Max(t => t.Id);
return maxId + 1;
}
#endregion
#region OwnerDraw +
private void lstTasks_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
try
{
// 与 ChargeStationManagementForm 表头保持一致的深蓝背景与白色加粗字体
using (var backBrush = new SolidBrush(Color.FromArgb(63, 81, 181))) // 深蓝(与 Charge 界面一致)
using (var textBrush = new SolidBrush(Color.White)) // 白色文字
using (var font = new Font("微软雅黑", 9, FontStyle.Bold))
{
e.Graphics.FillRectangle(backBrush, e.Bounds);
var sf = new StringFormat { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Near };
var rect = e.Bounds;
rect.Inflate(-8, 0);
e.Graphics.DrawString(e.Header.Text, font, textBrush, rect, sf);
// 分隔线
using (var pen = new Pen(Color.FromArgb(200, 200, 200)))
{
e.Graphics.DrawLine(pen, e.Bounds.Left, e.Bounds.Bottom - 1, e.Bounds.Right, e.Bounds.Bottom - 1);
}
}
}
catch
{
e.DrawBackground();
e.DrawText();
}
}
private void lstTasks_DrawItem(object sender, DrawListViewItemEventArgs e)
{
// 由 DrawSubItem 绘制全部内容以保证每列对齐
}
private void lstTasks_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
try
{
var item = e.Item;
bool selected = item.Selected;
Rectangle bounds = e.Bounds;
// 选中行颜色:与 ChargeStationManagementForm 保持一致的蓝色强调
Color selectedBack = Color.FromArgb(0, 120, 215);
Color selectedFore = Color.White;
// 非选中行交替背景
Color evenBack = Color.White;
Color oddBack = Color.FromArgb(250, 251, 253);
Color normalFore = Color.FromArgb(33, 33, 33);
// 填充背景
if (selected)
{
using (var selBrush = new SolidBrush(selectedBack))
{
e.Graphics.FillRectangle(selBrush, bounds);
}
}
else
{
using (var back = new SolidBrush(e.ItemIndex % 2 == 0 ? evenBack : oddBack))
{
e.Graphics.FillRectangle(back, bounds);
}
}
// 绘制文本(加一点内边距)
string text = e.SubItem.Text ?? string.Empty;
Color fore = selected ? selectedFore : normalFore;
TextFormatFlags flags = TextFormatFlags.Left | TextFormatFlags.VerticalCenter;
Rectangle textRect = bounds;
textRect.Inflate(-6, 0);
using (var font = new Font("微软雅黑", 9))
{
TextRenderer.DrawText(e.Graphics, text, font, textRect, fore, flags);
}
}
catch
{
e.DrawBackground();
e.DrawText();
}
}
#endregion
#region /
private void RenderListView()
{
try
{
if (lstTasks == null) return;
lstTasks.BeginUpdate();
lstTasks.Items.Clear();
foreach (var t in tasks)
{
var lvi = new ListViewItem(new[]
{
t.Id.ToString(), // ID 列
t.Kind.ToString(),
t.CurrentStationId.ToString(),
t.TargetStationId.ToString(),
t.TrafficControl.ToString(),
t.Priority.ToString(),
t.IsViaPoint ? "是" : "否",
t.StartType.ToString()
});
lstTasks.Items.Add(lvi);
}
lstTasks.EndUpdate();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"RenderListView failed: {ex}");
}
}
private void Save()
{
try
{
File.WriteAllText(jsonPath, JsonConvert.SerializeObject(tasks, Formatting.Indented));
}
catch (Exception ex)
{
MessageBox.Show("保存失败:" + ex.Message);
}
}
#endregion
#region /
private void UpdateSaveButtonText()
{
if (btnSave != null)
{
// 文案固定为"保存"
btnSave.Text = "保存";
}
}
private void btnSave_Click(object sender, EventArgs e)
{
try
{
// 从面板读取值,直接在界面内编辑/新增
Enum.TryParse<TaskKind>(cmbTaskKind?.SelectedItem?.ToString() ?? "Loop", out var kind);
Enum.TryParse<TaskStartType>(cmbStartType?.SelectedItem?.ToString() ?? "AutoLoop", out var st);
if (editingIndex >= 0 && editingIndex < tasks.Count)
{
// 更新模式:保留原有ID
var existingTask = tasks[editingIndex];
existingTask.Kind = kind;
existingTask.CurrentStationId = (int)(numCurrent?.Value ?? 0);
existingTask.TargetStationId = (int)(numTarget?.Value ?? 0);
existingTask.TrafficControl = (int)(numTraffic?.Value ?? 0);
existingTask.Priority = (int)(numPriority?.Value ?? 1);
existingTask.IsViaPoint = chkViaPoint?.Checked ?? false;
existingTask.StartType = st;
}
else
{
// 新增模式:自动分配新ID
var t = new LoopTask
{
Id = GetNextTaskId(), // 自增ID
Kind = kind,
CurrentStationId = (int)(numCurrent?.Value ?? 0),
TargetStationId = (int)(numTarget?.Value ?? 0),
TrafficControl = (int)(numTraffic?.Value ?? 0),
Priority = (int)(numPriority?.Value ?? 1),
IsViaPoint = chkViaPoint?.Checked ?? false,
StartType = st
};
tasks.Add(t);
}
Save();
RenderListView();
// 恢复新增状态
editingIndex = -1;
UpdateSaveButtonText();
ClearPanelInputs();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"btnSave_Click error: {ex}");
MessageBox.Show("操作失败:" + ex.Message);
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
// 取消编辑,清空面板并回到"添加"模式
editingIndex = -1;
UpdateSaveButtonText();
ClearPanelInputs();
}
private void btnEdit_Click(object sender, EventArgs e)
{
try
{
if (lstTasks == null || lstTasks.SelectedIndices.Count == 0) return;
int idx = lstTasks.SelectedIndices[0];
if (idx < 0 || idx >= tasks.Count) return;
editingIndex = idx;
LoadTaskToPanel(tasks[idx]);
UpdateSaveButtonText();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"btnEdit_Click error: {ex}");
}
}
private void btnDelete_Click(object sender, EventArgs e)
{
// 兼容旧的删除按钮:复用统一删除逻辑
OnDeleteSelectedTasks();
}
#endregion
#region
private void lstTasks_MouseDoubleClick(object sender, MouseEventArgs e)
{
try
{
if (lstTasks == null) return;
var item = lstTasks.GetItemAt(e.X, e.Y);
if (item == null) return;
int idx = item.Index;
if (idx < 0 || idx >= tasks.Count) return;
editingIndex = idx;
LoadTaskToPanel(tasks[idx]);
UpdateSaveButtonText();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"lstTasks_MouseDoubleClick error: {ex}");
}
}
#endregion
#region
private void LoadTaskToPanel(LoopTask t)
{
if (t == null) return;
try
{
// 显示当前编辑的任务ID(只读显示)
if (lblEditingId != null) lblEditingId.Text = $"编辑任务 ID: {t.Id}";
if (cmbTaskKind != null) cmbTaskKind.SelectedItem = t.Kind.ToString();
if (numCurrent != null) numCurrent.Value = Math.Max(numCurrent.Minimum, Math.Min(numCurrent.Maximum, t.CurrentStationId));
if (numTarget != null) numTarget.Value = Math.Max(numTarget.Minimum, Math.Min(numTarget.Maximum, t.TargetStationId));
if (numTraffic != null) numTraffic.Value = Math.Max(numTraffic.Minimum, Math.Min(numTraffic.Maximum, t.TrafficControl));
if (numPriority != null) numPriority.Value = Math.Max(numPriority.Minimum, Math.Min(numPriority.Maximum, t.Priority));
if (chkViaPoint != null) chkViaPoint.Checked = t.IsViaPoint;
if (cmbStartType != null) cmbStartType.SelectedItem = t.StartType.ToString();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"LoadTaskToPanel error: {ex}");
}
}
private void ClearPanelInputs()
{
try
{
// 清除编辑ID显示
if (lblEditingId != null) lblEditingId.Text = "新增任务";
if (cmbTaskKind != null) cmbTaskKind.SelectedIndex = 0;
if (numCurrent != null) numCurrent.Value = 0;
if (numTarget != null) numTarget.Value = 0;
if (numTraffic != null) numTraffic.Value = 0;
if (numPriority != null) numPriority.Value = 1;
if (chkViaPoint != null) chkViaPoint.Checked = false;
if (cmbStartType != null) cmbStartType.SelectedIndex = 3;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"ClearPanelInputs error: {ex}");
}
}
#endregion
}
}
}
-120
View File
@@ -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>
@@ -22,7 +22,6 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Win32.SafeHandles;
namespace StandardScene.Chained
@@ -377,7 +376,7 @@ namespace StandardScene.Chained
{
G.pushStatus("选择小车");
var selected = SimpleMonitor.selected.ToArray();
if (selected.Length == 0) { MessageBox.Show("请先选择需要控制的小车!"); return; }
if (selected.Length == 0) { CycleUiHelper.Alert("提示", "请先选择需要控制的小车!"); return; }
var obj = selected[0];
if (obj is Car car)
{
@@ -401,7 +400,7 @@ namespace StandardScene.Chained
}
else
{
MessageBox.Show("请选择需要控制的小车!");
CycleUiHelper.Alert("提示", "请选择需要控制的小车!");
}
}
catch
@@ -428,7 +427,7 @@ namespace StandardScene.Chained
{
G.pushStatus("选择小车");
var selected = SimpleMonitor.selected.ToArray();
if (selected.Length == 0) { MessageBox.Show("请先选择需要控制的小车!"); return; }
if (selected.Length == 0) { CycleUiHelper.Alert("提示", "请先选择需要控制的小车!"); return; }
var obj = selected[0];
if (obj is Car car)
{
@@ -453,7 +452,7 @@ namespace StandardScene.Chained
}
else
{
MessageBox.Show("请选择需要控制的小车!");
CycleUiHelper.Alert("提示", "请选择需要控制的小车!");
}
}
catch
@@ -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"/>,批量刷新 UI500ms 节流),最多显示 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 = "已启动";
+2 -2
View File
@@ -7,7 +7,6 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using SimpleLite.RCS;
using SimpleLite.RCS.CarTypes;
using SimpleLite.CADTools;
@@ -20,6 +19,7 @@ using SimpleCore.PropType;
using SimpleCore.Traffic;
using StandardScene.InterLock;
using StandardScene.Model;
using StandardScene.Utils;
using static StandardScene.Chained.ChainedDeliveryMission;
namespace StandardScene
@@ -39,7 +39,7 @@ namespace StandardScene
var cars = string.Join(",", loopingCar.Select(p => $"{p.id}"));
var msg = $"小车:{cars}间发生死锁" +
$"请及时人工介入处理!!!!";
MessageBox.Show(msg);
CycleUiHelper.Alert("死锁提醒", msg);
}
catch { }
};
@@ -417,8 +417,8 @@ ChargeStationManagementExample.InitializeTestData();
## 📊 系统要求
### 软件要求
- .NET Framework 4.5 或更高版本
- Windows Forms
- .NET 8net8.0-windows),宿主 `SimpleLite.exe`
- Windows Forms(充电模块界面尚未迁移到 CycleGUI,过渡期仍依赖)
- Newtonsoft.JsonNuGet
### 硬件要求
@@ -1,608 +0,0 @@
namespace StandardScene.ExtendDevice.ButtonBox
{
partial class ButtonBoxManager
{
/// <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()
{
this.buttonBoxListView = new System.Windows.Forms.ListView();
this.columnHeaderBoxIndex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderIp = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderPort = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.groupBoxButtonBox = new System.Windows.Forms.GroupBox();
this.btnSaveButtonBox = new System.Windows.Forms.Button();
this.btnDeleteButtonBox = new System.Windows.Forms.Button();
this.btnAddButtonBox = new System.Windows.Forms.Button();
this.labelType = new System.Windows.Forms.Label();
this.comboBoxType = new System.Windows.Forms.ComboBox();
this.labelBoxIndex = new System.Windows.Forms.Label();
this.textBoxBoxIndex = new System.Windows.Forms.TextBox();
this.labelPort = new System.Windows.Forms.Label();
this.textBoxPort = new System.Windows.Forms.TextBox();
this.labelIp = new System.Windows.Forms.Label();
this.textBoxIp = new System.Windows.Forms.TextBox();
this.buttonListView = new System.Windows.Forms.ListView();
this.columnHeaderButtonIndex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderTriggerMission = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderTriggerMethod = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderTriggerMethodParams = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderTriggerState = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderTriggerDelay = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.groupBoxButton = new System.Windows.Forms.GroupBox();
this.btnSaveButton = new System.Windows.Forms.Button();
this.btnDeleteButton = new System.Windows.Forms.Button();
this.btnAddButton = new System.Windows.Forms.Button();
this.labelTriggerMethodParams = new System.Windows.Forms.Label();
this.textBoxTriggerMethodParams = new System.Windows.Forms.TextBox();
this.labelTriggerMethod = new System.Windows.Forms.Label();
this.textBoxTriggerMethod = new System.Windows.Forms.TextBox();
this.labelTriggerMission = new System.Windows.Forms.Label();
this.textBoxTriggerMission = new System.Windows.Forms.TextBox();
this.labelButtonIndex = new System.Windows.Forms.Label();
this.textBoxButtonIndex = new System.Windows.Forms.TextBox();
this.labelTriggerState = new System.Windows.Forms.Label();
this.comboBoxTriggerState = new System.Windows.Forms.ComboBox();
this.labelTriggerDelay = new System.Windows.Forms.Label();
this.textBoxTriggerDelay = new System.Windows.Forms.TextBox();
this.labelTitle = new System.Windows.Forms.Label();
this.groupBoxButtonBox.SuspendLayout();
this.groupBoxButton.SuspendLayout();
this.SuspendLayout();
//
// buttonBoxListView
//
this.buttonBoxListView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.buttonBoxListView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.buttonBoxListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeaderBoxIndex,
this.columnHeaderIp,
this.columnHeaderPort,
this.columnHeaderType});
this.buttonBoxListView.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.buttonBoxListView.FullRowSelect = true;
this.buttonBoxListView.GridLines = true;
this.buttonBoxListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.buttonBoxListView.HideSelection = false;
this.buttonBoxListView.Location = new System.Drawing.Point(15, 55);
this.buttonBoxListView.MultiSelect = false;
this.buttonBoxListView.Name = "buttonBoxListView";
this.buttonBoxListView.OwnerDraw = true;
this.buttonBoxListView.Size = new System.Drawing.Size(450, 290);
this.buttonBoxListView.TabIndex = 0;
this.buttonBoxListView.UseCompatibleStateImageBehavior = false;
this.buttonBoxListView.View = System.Windows.Forms.View.Details;
this.buttonBoxListView.SelectedIndexChanged += new System.EventHandler(this.buttonBoxListView_SelectedIndexChanged);
//
// columnHeaderBoxIndex
//
this.columnHeaderBoxIndex.Text = "编码";
this.columnHeaderBoxIndex.Width = 70;
//
// columnHeaderIp
//
this.columnHeaderIp.Text = "IP地址";
this.columnHeaderIp.Width = 130;
//
// columnHeaderPort
//
this.columnHeaderPort.Text = "端口";
this.columnHeaderPort.Width = 90;
//
// columnHeaderType
//
this.columnHeaderType.Text = "类型";
this.columnHeaderType.Width = 140;
//
// groupBoxButtonBox
//
this.groupBoxButtonBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.groupBoxButtonBox.Controls.Add(this.btnSaveButtonBox);
this.groupBoxButtonBox.Controls.Add(this.btnDeleteButtonBox);
this.groupBoxButtonBox.Controls.Add(this.btnAddButtonBox);
this.groupBoxButtonBox.Controls.Add(this.labelType);
this.groupBoxButtonBox.Controls.Add(this.comboBoxType);
this.groupBoxButtonBox.Controls.Add(this.labelBoxIndex);
this.groupBoxButtonBox.Controls.Add(this.textBoxBoxIndex);
this.groupBoxButtonBox.Controls.Add(this.labelPort);
this.groupBoxButtonBox.Controls.Add(this.textBoxPort);
this.groupBoxButtonBox.Controls.Add(this.labelIp);
this.groupBoxButtonBox.Controls.Add(this.textBoxIp);
this.groupBoxButtonBox.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.groupBoxButtonBox.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(68)))), ((int)(((byte)(68)))), ((int)(((byte)(68)))));
this.groupBoxButtonBox.Location = new System.Drawing.Point(15, 360);
this.groupBoxButtonBox.Name = "groupBoxButtonBox";
this.groupBoxButtonBox.Padding = new System.Windows.Forms.Padding(12, 10, 12, 12);
this.groupBoxButtonBox.Size = new System.Drawing.Size(450, 250);
this.groupBoxButtonBox.TabIndex = 1;
this.groupBoxButtonBox.TabStop = false;
this.groupBoxButtonBox.Text = "按钮盒信息";
//
// btnSaveButtonBox
//
this.btnSaveButtonBox.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(122)))), ((int)(((byte)(204)))));
this.btnSaveButtonBox.FlatAppearance.BorderSize = 0;
this.btnSaveButtonBox.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(92)))), ((int)(((byte)(153)))));
this.btnSaveButtonBox.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(102)))), ((int)(((byte)(170)))));
this.btnSaveButtonBox.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnSaveButtonBox.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnSaveButtonBox.ForeColor = System.Drawing.Color.White;
this.btnSaveButtonBox.Location = new System.Drawing.Point(330, 200);
this.btnSaveButtonBox.Name = "btnSaveButtonBox";
this.btnSaveButtonBox.Size = new System.Drawing.Size(100, 38);
this.btnSaveButtonBox.TabIndex = 10;
this.btnSaveButtonBox.Text = "保存";
this.btnSaveButtonBox.UseVisualStyleBackColor = false;
this.btnSaveButtonBox.Click += new System.EventHandler(this.btnSaveButtonBox_Click);
//
// btnDeleteButtonBox
//
this.btnDeleteButtonBox.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(53)))), ((int)(((byte)(69)))));
this.btnDeleteButtonBox.FlatAppearance.BorderSize = 0;
this.btnDeleteButtonBox.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(165)))), ((int)(((byte)(40)))), ((int)(((byte)(52)))));
this.btnDeleteButtonBox.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(187)))), ((int)(((byte)(45)))), ((int)(((byte)(59)))));
this.btnDeleteButtonBox.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnDeleteButtonBox.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnDeleteButtonBox.ForeColor = System.Drawing.Color.White;
this.btnDeleteButtonBox.Location = new System.Drawing.Point(220, 200);
this.btnDeleteButtonBox.Name = "btnDeleteButtonBox";
this.btnDeleteButtonBox.Size = new System.Drawing.Size(100, 38);
this.btnDeleteButtonBox.TabIndex = 9;
this.btnDeleteButtonBox.Text = "删除";
this.btnDeleteButtonBox.UseVisualStyleBackColor = false;
this.btnDeleteButtonBox.Click += new System.EventHandler(this.btnDeleteButtonBox_Click);
//
// btnAddButtonBox
//
this.btnAddButtonBox.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(167)))), ((int)(((byte)(69)))));
this.btnAddButtonBox.FlatAppearance.BorderSize = 0;
this.btnAddButtonBox.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(125)))), ((int)(((byte)(52)))));
this.btnAddButtonBox.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(33)))), ((int)(((byte)(136)))), ((int)(((byte)(56)))));
this.btnAddButtonBox.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnAddButtonBox.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnAddButtonBox.ForeColor = System.Drawing.Color.White;
this.btnAddButtonBox.Location = new System.Drawing.Point(110, 200);
this.btnAddButtonBox.Name = "btnAddButtonBox";
this.btnAddButtonBox.Size = new System.Drawing.Size(100, 38);
this.btnAddButtonBox.TabIndex = 8;
this.btnAddButtonBox.Text = "添加";
this.btnAddButtonBox.UseVisualStyleBackColor = false;
this.btnAddButtonBox.Click += new System.EventHandler(this.btnAddButtonBox_Click);
//
// labelType
//
this.labelType.AutoSize = true;
this.labelType.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelType.Location = new System.Drawing.Point(28, 168);
this.labelType.Name = "labelType";
this.labelType.Size = new System.Drawing.Size(65, 24);
this.labelType.TabIndex = 7;
this.labelType.Text = "类型:";
//
// comboBoxType
//
this.comboBoxType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxType.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.comboBoxType.FormattingEnabled = true;
this.comboBoxType.Location = new System.Drawing.Point(110, 165);
this.comboBoxType.Name = "comboBoxType";
this.comboBoxType.Size = new System.Drawing.Size(320, 32);
this.comboBoxType.TabIndex = 6;
//
// labelBoxIndex
//
this.labelBoxIndex.AutoSize = true;
this.labelBoxIndex.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelBoxIndex.Location = new System.Drawing.Point(28, 48);
this.labelBoxIndex.Name = "labelBoxIndex";
this.labelBoxIndex.Size = new System.Drawing.Size(65, 24);
this.labelBoxIndex.TabIndex = 1;
this.labelBoxIndex.Text = "编码:";
//
// textBoxBoxIndex
//
this.textBoxBoxIndex.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxBoxIndex.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxBoxIndex.Location = new System.Drawing.Point(110, 45);
this.textBoxBoxIndex.Name = "textBoxBoxIndex";
this.textBoxBoxIndex.Size = new System.Drawing.Size(320, 30);
this.textBoxBoxIndex.TabIndex = 0;
//
// labelIp
//
this.labelIp.AutoSize = true;
this.labelIp.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelIp.Location = new System.Drawing.Point(18, 88);
this.labelIp.Name = "labelIp";
this.labelIp.Size = new System.Drawing.Size(85, 24);
this.labelIp.TabIndex = 3;
this.labelIp.Text = "IP地址:";
//
// textBoxIp
//
this.textBoxIp.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxIp.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxIp.Location = new System.Drawing.Point(110, 85);
this.textBoxIp.Name = "textBoxIp";
this.textBoxIp.Size = new System.Drawing.Size(320, 30);
this.textBoxIp.TabIndex = 2;
this.textBoxIp.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))));
//
// labelPort
//
this.labelPort.AutoSize = true;
this.labelPort.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelPort.Location = new System.Drawing.Point(28, 128);
this.labelPort.Name = "labelPort";
this.labelPort.Size = new System.Drawing.Size(65, 24);
this.labelPort.TabIndex = 5;
this.labelPort.Text = "端口:";
//
// textBoxPort
//
this.textBoxPort.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxPort.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxPort.Location = new System.Drawing.Point(110, 125);
this.textBoxPort.Name = "textBoxPort";
this.textBoxPort.Size = new System.Drawing.Size(320, 30);
this.textBoxPort.TabIndex = 4;
//
// buttonListView
//
this.buttonListView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.buttonListView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.buttonListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeaderButtonIndex,
this.columnHeaderTriggerState,
this.columnHeaderTriggerDelay,
this.columnHeaderTriggerMission,
this.columnHeaderTriggerMethod,
this.columnHeaderTriggerMethodParams});
this.buttonListView.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.buttonListView.FullRowSelect = true;
this.buttonListView.GridLines = true;
this.buttonListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.buttonListView.HideSelection = false;
this.buttonListView.Location = new System.Drawing.Point(483, 55);
this.buttonListView.MultiSelect = false;
this.buttonListView.Name = "buttonListView";
this.buttonListView.OwnerDraw = true;
this.buttonListView.Size = new System.Drawing.Size(700, 290);
this.buttonListView.TabIndex = 2;
this.buttonListView.UseCompatibleStateImageBehavior = false;
this.buttonListView.View = System.Windows.Forms.View.Details;
this.buttonListView.SelectedIndexChanged += new System.EventHandler(this.buttonListView_SelectedIndexChanged);
//
// columnHeaderButtonIndex
//
this.columnHeaderButtonIndex.Text = "编码";
this.columnHeaderButtonIndex.Width = 70;
//
// columnHeaderTriggerState
//
this.columnHeaderTriggerState.Text = "触发状态";
this.columnHeaderTriggerState.Width = 100;
//
// columnHeaderTriggerDelay
//
this.columnHeaderTriggerDelay.Text = "触发延迟";
this.columnHeaderTriggerDelay.Width = 90;
//
// columnHeaderTriggerMission
//
this.columnHeaderTriggerMission.Text = "触发任务";
this.columnHeaderTriggerMission.Width = 140;
//
// columnHeaderTriggerMethod
//
this.columnHeaderTriggerMethod.Text = "触发方法";
this.columnHeaderTriggerMethod.Width = 140;
//
// columnHeaderTriggerMethodParams
//
this.columnHeaderTriggerMethodParams.Text = "方法参数";
this.columnHeaderTriggerMethodParams.Width = 160;
//
// groupBoxButton
//
this.groupBoxButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.groupBoxButton.Controls.Add(this.btnSaveButton);
this.groupBoxButton.Controls.Add(this.btnDeleteButton);
this.groupBoxButton.Controls.Add(this.btnAddButton);
this.groupBoxButton.Controls.Add(this.labelTriggerMethodParams);
this.groupBoxButton.Controls.Add(this.textBoxTriggerMethodParams);
this.groupBoxButton.Controls.Add(this.labelTriggerMethod);
this.groupBoxButton.Controls.Add(this.textBoxTriggerMethod);
this.groupBoxButton.Controls.Add(this.labelTriggerMission);
this.groupBoxButton.Controls.Add(this.textBoxTriggerMission);
this.groupBoxButton.Controls.Add(this.labelButtonIndex);
this.groupBoxButton.Controls.Add(this.textBoxButtonIndex);
this.groupBoxButton.Controls.Add(this.labelTriggerState);
this.groupBoxButton.Controls.Add(this.comboBoxTriggerState);
this.groupBoxButton.Controls.Add(this.labelTriggerDelay);
this.groupBoxButton.Controls.Add(this.textBoxTriggerDelay);
this.groupBoxButton.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.groupBoxButton.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(68)))), ((int)(((byte)(68)))), ((int)(((byte)(68)))));
this.groupBoxButton.Location = new System.Drawing.Point(483, 360);
this.groupBoxButton.Name = "groupBoxButton";
this.groupBoxButton.Padding = new System.Windows.Forms.Padding(12, 10, 12, 12);
this.groupBoxButton.Size = new System.Drawing.Size(700, 250);
this.groupBoxButton.TabIndex = 3;
this.groupBoxButton.TabStop = false;
this.groupBoxButton.Text = "按钮信息";
//
// btnSaveButton
//
this.btnSaveButton.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(122)))), ((int)(((byte)(204)))));
this.btnSaveButton.FlatAppearance.BorderSize = 0;
this.btnSaveButton.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(92)))), ((int)(((byte)(153)))));
this.btnSaveButton.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(102)))), ((int)(((byte)(170)))));
this.btnSaveButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnSaveButton.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnSaveButton.ForeColor = System.Drawing.Color.White;
this.btnSaveButton.Location = new System.Drawing.Point(580, 180);
this.btnSaveButton.Name = "btnSaveButton";
this.btnSaveButton.Size = new System.Drawing.Size(100, 38);
this.btnSaveButton.TabIndex = 13;
this.btnSaveButton.Text = "保存";
this.btnSaveButton.UseVisualStyleBackColor = false;
this.btnSaveButton.Click += new System.EventHandler(this.btnSaveButton_Click);
//
// btnDeleteButton
//
this.btnDeleteButton.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(53)))), ((int)(((byte)(69)))));
this.btnDeleteButton.FlatAppearance.BorderSize = 0;
this.btnDeleteButton.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(165)))), ((int)(((byte)(40)))), ((int)(((byte)(52)))));
this.btnDeleteButton.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(187)))), ((int)(((byte)(45)))), ((int)(((byte)(59)))));
this.btnDeleteButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnDeleteButton.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnDeleteButton.ForeColor = System.Drawing.Color.White;
this.btnDeleteButton.Location = new System.Drawing.Point(470, 180);
this.btnDeleteButton.Name = "btnDeleteButton";
this.btnDeleteButton.Size = new System.Drawing.Size(100, 38);
this.btnDeleteButton.TabIndex = 12;
this.btnDeleteButton.Text = "删除";
this.btnDeleteButton.UseVisualStyleBackColor = false;
this.btnDeleteButton.Click += new System.EventHandler(this.btnDeleteButton_Click);
//
// btnAddButton
//
this.btnAddButton.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(167)))), ((int)(((byte)(69)))));
this.btnAddButton.FlatAppearance.BorderSize = 0;
this.btnAddButton.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(125)))), ((int)(((byte)(52)))));
this.btnAddButton.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(33)))), ((int)(((byte)(136)))), ((int)(((byte)(56)))));
this.btnAddButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnAddButton.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnAddButton.ForeColor = System.Drawing.Color.White;
this.btnAddButton.Location = new System.Drawing.Point(360, 180);
this.btnAddButton.Name = "btnAddButton";
this.btnAddButton.Size = new System.Drawing.Size(100, 38);
this.btnAddButton.TabIndex = 11;
this.btnAddButton.Text = "添加";
this.btnAddButton.UseVisualStyleBackColor = false;
this.btnAddButton.Click += new System.EventHandler(this.btnAddButton_Click);
//
// labelTriggerMethodParams
//
this.labelTriggerMethodParams.AutoSize = true;
this.labelTriggerMethodParams.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelTriggerMethodParams.Location = new System.Drawing.Point(370, 128);
this.labelTriggerMethodParams.Name = "labelTriggerMethodParams";
this.labelTriggerMethodParams.Size = new System.Drawing.Size(103, 24);
this.labelTriggerMethodParams.TabIndex = 11;
this.labelTriggerMethodParams.Text = "方法参数:";
//
// textBoxTriggerMethodParams
//
this.textBoxTriggerMethodParams.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxTriggerMethodParams.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxTriggerMethodParams.Location = new System.Drawing.Point(490, 125);
this.textBoxTriggerMethodParams.Name = "textBoxTriggerMethodParams";
this.textBoxTriggerMethodParams.Size = new System.Drawing.Size(190, 30);
this.textBoxTriggerMethodParams.TabIndex = 10;
//
// labelTriggerState
//
this.labelTriggerState.AutoSize = true;
this.labelTriggerState.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelTriggerState.Location = new System.Drawing.Point(370, 48);
this.labelTriggerState.Name = "labelTriggerState";
this.labelTriggerState.Size = new System.Drawing.Size(103, 24);
this.labelTriggerState.TabIndex = 3;
this.labelTriggerState.Text = "触发状态:";
//
// comboBoxTriggerState
//
this.comboBoxTriggerState.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxTriggerState.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.comboBoxTriggerState.FormattingEnabled = true;
this.comboBoxTriggerState.Location = new System.Drawing.Point(490, 45);
this.comboBoxTriggerState.Name = "comboBoxTriggerState";
this.comboBoxTriggerState.Size = new System.Drawing.Size(190, 32);
this.comboBoxTriggerState.TabIndex = 2;
//
// labelTriggerDelay
//
this.labelTriggerDelay.AutoSize = true;
this.labelTriggerDelay.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelTriggerDelay.Location = new System.Drawing.Point(28, 88);
this.labelTriggerDelay.Name = "labelTriggerDelay";
this.labelTriggerDelay.Size = new System.Drawing.Size(103, 24);
this.labelTriggerDelay.TabIndex = 5;
this.labelTriggerDelay.Text = "触发延迟:";
//
// textBoxTriggerDelay
//
this.textBoxTriggerDelay.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxTriggerDelay.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxTriggerDelay.Location = new System.Drawing.Point(150, 85);
this.textBoxTriggerDelay.Name = "textBoxTriggerDelay";
this.textBoxTriggerDelay.Size = new System.Drawing.Size(200, 30);
this.textBoxTriggerDelay.TabIndex = 4;
//
// labelTriggerMethod
//
this.labelTriggerMethod.AutoSize = true;
this.labelTriggerMethod.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelTriggerMethod.Location = new System.Drawing.Point(28, 128);
this.labelTriggerMethod.Name = "labelTriggerMethod";
this.labelTriggerMethod.Size = new System.Drawing.Size(103, 24);
this.labelTriggerMethod.TabIndex = 9;
this.labelTriggerMethod.Text = "触发方法:";
//
// textBoxTriggerMethod
//
this.textBoxTriggerMethod.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxTriggerMethod.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxTriggerMethod.Location = new System.Drawing.Point(150, 125);
this.textBoxTriggerMethod.Name = "textBoxTriggerMethod";
this.textBoxTriggerMethod.Size = new System.Drawing.Size(200, 30);
this.textBoxTriggerMethod.TabIndex = 8;
//
// labelTriggerMission
//
this.labelTriggerMission.AutoSize = true;
this.labelTriggerMission.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelTriggerMission.Location = new System.Drawing.Point(370, 88);
this.labelTriggerMission.Name = "labelTriggerMission";
this.labelTriggerMission.Size = new System.Drawing.Size(103, 24);
this.labelTriggerMission.TabIndex = 7;
this.labelTriggerMission.Text = "触发任务:";
//
// textBoxTriggerMission
//
this.textBoxTriggerMission.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxTriggerMission.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxTriggerMission.Location = new System.Drawing.Point(490, 85);
this.textBoxTriggerMission.Name = "textBoxTriggerMission";
this.textBoxTriggerMission.Size = new System.Drawing.Size(190, 30);
this.textBoxTriggerMission.TabIndex = 6;
//
// labelButtonIndex
//
this.labelButtonIndex.AutoSize = true;
this.labelButtonIndex.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelButtonIndex.Location = new System.Drawing.Point(28, 48);
this.labelButtonIndex.Name = "labelButtonIndex";
this.labelButtonIndex.Size = new System.Drawing.Size(65, 24);
this.labelButtonIndex.TabIndex = 1;
this.labelButtonIndex.Text = "编码:";
//
// textBoxButtonIndex
//
this.textBoxButtonIndex.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxButtonIndex.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxButtonIndex.Location = new System.Drawing.Point(150, 45);
this.textBoxButtonIndex.Name = "textBoxButtonIndex";
this.textBoxButtonIndex.Size = new System.Drawing.Size(200, 30);
this.textBoxButtonIndex.TabIndex = 0;
//
// labelTitle
//
this.labelTitle.AutoSize = true;
this.labelTitle.Font = new System.Drawing.Font("微软雅黑", 16F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelTitle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(51)))), ((int)(((byte)(51)))), ((int)(((byte)(51)))));
this.labelTitle.Location = new System.Drawing.Point(15, 12);
this.labelTitle.Name = "labelTitle";
this.labelTitle.Size = new System.Drawing.Size(150, 42);
this.labelTitle.TabIndex = 4;
this.labelTitle.Text = "按钮盒管理";
//
// ButtonBoxManager
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(245)))), ((int)(((byte)(245)))), ((int)(((byte)(247)))));
this.ClientSize = new System.Drawing.Size(1200, 620);
this.Controls.Add(this.labelTitle);
this.Controls.Add(this.groupBoxButton);
this.Controls.Add(this.buttonListView);
this.Controls.Add(this.groupBoxButtonBox);
this.Controls.Add(this.buttonBoxListView);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.MinimumSize = new System.Drawing.Size(1200, 620);
this.Name = "ButtonBoxManager";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "按钮盒管理";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ButtonBoxManager_FormClosing);
this.Load += new System.EventHandler(this.ButtonBoxManager_Load);
this.groupBoxButtonBox.ResumeLayout(false);
this.groupBoxButtonBox.PerformLayout();
this.groupBoxButton.ResumeLayout(false);
this.groupBoxButton.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ListView buttonBoxListView;
private System.Windows.Forms.ColumnHeader columnHeaderBoxIndex;
private System.Windows.Forms.ColumnHeader columnHeaderIp;
private System.Windows.Forms.ColumnHeader columnHeaderPort;
private System.Windows.Forms.ColumnHeader columnHeaderType;
private System.Windows.Forms.GroupBox groupBoxButtonBox;
private System.Windows.Forms.TextBox textBoxIp;
private System.Windows.Forms.Label labelIp;
private System.Windows.Forms.Label labelPort;
private System.Windows.Forms.TextBox textBoxPort;
private System.Windows.Forms.Label labelBoxIndex;
private System.Windows.Forms.TextBox textBoxBoxIndex;
private System.Windows.Forms.Label labelType;
private System.Windows.Forms.ComboBox comboBoxType;
private System.Windows.Forms.Button btnAddButtonBox;
private System.Windows.Forms.Button btnDeleteButtonBox;
private System.Windows.Forms.Button btnSaveButtonBox;
private System.Windows.Forms.ListView buttonListView;
private System.Windows.Forms.ColumnHeader columnHeaderButtonIndex;
private System.Windows.Forms.ColumnHeader columnHeaderTriggerMission;
private System.Windows.Forms.ColumnHeader columnHeaderTriggerMethod;
private System.Windows.Forms.ColumnHeader columnHeaderTriggerMethodParams;
private System.Windows.Forms.GroupBox groupBoxButton;
private System.Windows.Forms.Label labelButtonIndex;
private System.Windows.Forms.TextBox textBoxButtonIndex;
private System.Windows.Forms.Label labelTriggerMission;
private System.Windows.Forms.TextBox textBoxTriggerMission;
private System.Windows.Forms.Label labelTriggerMethod;
private System.Windows.Forms.TextBox textBoxTriggerMethod;
private System.Windows.Forms.Label labelTriggerMethodParams;
private System.Windows.Forms.TextBox textBoxTriggerMethodParams;
private System.Windows.Forms.Label labelTriggerState;
private System.Windows.Forms.ComboBox comboBoxTriggerState;
private System.Windows.Forms.Label labelTriggerDelay;
private System.Windows.Forms.TextBox textBoxTriggerDelay;
private System.Windows.Forms.ColumnHeader columnHeaderTriggerState;
private System.Windows.Forms.ColumnHeader columnHeaderTriggerDelay;
private System.Windows.Forms.Button btnAddButton;
private System.Windows.Forms.Button btnDeleteButton;
private System.Windows.Forms.Button btnSaveButton;
private System.Windows.Forms.Label labelTitle;
}
}
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>
@@ -6,7 +6,6 @@ using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using LessokajiWeaverUtilities.MagicAttributes;
using LessokajiWeaverUtilities.Utilities;
using SimpleLite;
@@ -768,39 +767,8 @@ namespace StandardScene.ExtendDevice.ButtonBox
[I18N.DocumentTranslation(Name = "Open Manager", locale = "en")]
public static void OpenViewer()
{
try
{
var manager = ButtonBoxManager.Instance;
// 确保窗体没有被销毁
if (manager.IsDisposed)
{
// 如果窗体被销毁,单例会自动重新创建
manager = ButtonBoxManager.Instance;
}
if (manager.Visible)
{
// 如果界面已经可见,将其激活并置于最前
if (manager.WindowState == FormWindowState.Minimized)
{
manager.WindowState = FormWindowState.Normal;
}
manager.Activate();
manager.BringToFront();
}
else
{
// 如果界面不可见,显示它
manager.Show();
manager.Activate();
}
}
catch (Exception ex)
{
MessageBox.Show($"打开按钮盒管理界面失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
try { ButtonBoxManager.Open(); }
catch (Exception ex) { CycleUiHelper.Alert("错误", $"打开按钮盒管理界面失败: {ex.Message}"); }
}
}
}
@@ -1,521 +0,0 @@
namespace StandardScene.ExtendDevice.Door
{
partial class DoorManager
{
/// <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()
{
this.doorControllerListView = new System.Windows.Forms.ListView();
this.columnHeaderControllerIndex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderIp = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderPort = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.groupBoxController = new System.Windows.Forms.GroupBox();
this.btnSaveController = new System.Windows.Forms.Button();
this.btnDeleteController = new System.Windows.Forms.Button();
this.btnAddController = new System.Windows.Forms.Button();
this.labelType = new System.Windows.Forms.Label();
this.comboBoxType = new System.Windows.Forms.ComboBox();
this.labelControllerIndex = new System.Windows.Forms.Label();
this.textBoxControllerIndex = new System.Windows.Forms.TextBox();
this.labelPort = new System.Windows.Forms.Label();
this.textBoxPort = new System.Windows.Forms.TextBox();
this.labelIp = new System.Windows.Forms.Label();
this.textBoxIp = new System.Windows.Forms.TextBox();
this.doorListView = new System.Windows.Forms.ListView();
this.columnHeaderDoorIndex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderControlAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderOpenStatusAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.groupBoxDoor = new System.Windows.Forms.GroupBox();
this.btnSaveDoor = new System.Windows.Forms.Button();
this.btnDeleteDoor = new System.Windows.Forms.Button();
this.btnAddDoor = new System.Windows.Forms.Button();
this.labelOpenStatusAddress = new System.Windows.Forms.Label();
this.textBoxOpenStatusAddress = new System.Windows.Forms.TextBox();
this.labelControlAddress = new System.Windows.Forms.Label();
this.textBoxControlAddress = new System.Windows.Forms.TextBox();
this.labelDoorIndex = new System.Windows.Forms.Label();
this.textBoxDoorIndex = new System.Windows.Forms.TextBox();
this.labelTitle = new System.Windows.Forms.Label();
this.groupBoxController.SuspendLayout();
this.groupBoxDoor.SuspendLayout();
this.SuspendLayout();
//
// doorControllerListView
//
this.doorControllerListView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.doorControllerListView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.doorControllerListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeaderControllerIndex,
this.columnHeaderIp,
this.columnHeaderPort,
this.columnHeaderType});
this.doorControllerListView.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.doorControllerListView.FullRowSelect = true;
this.doorControllerListView.GridLines = true;
this.doorControllerListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.doorControllerListView.HideSelection = false;
this.doorControllerListView.Location = new System.Drawing.Point(15, 55);
this.doorControllerListView.MultiSelect = false;
this.doorControllerListView.Name = "doorControllerListView";
this.doorControllerListView.OwnerDraw = true;
this.doorControllerListView.Size = new System.Drawing.Size(450, 290);
this.doorControllerListView.TabIndex = 0;
this.doorControllerListView.UseCompatibleStateImageBehavior = false;
this.doorControllerListView.View = System.Windows.Forms.View.Details;
this.doorControllerListView.SelectedIndexChanged += new System.EventHandler(this.doorControllerListView_SelectedIndexChanged);
//
// columnHeaderControllerIndex
//
this.columnHeaderControllerIndex.Text = "编码";
this.columnHeaderControllerIndex.Width = 70;
//
// columnHeaderIp
//
this.columnHeaderIp.Text = "IP地址";
this.columnHeaderIp.Width = 130;
//
// columnHeaderPort
//
this.columnHeaderPort.Text = "端口";
this.columnHeaderPort.Width = 90;
//
// columnHeaderType
//
this.columnHeaderType.Text = "类型";
this.columnHeaderType.Width = 140;
//
// groupBoxController
//
this.groupBoxController.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.groupBoxController.Controls.Add(this.btnSaveController);
this.groupBoxController.Controls.Add(this.btnDeleteController);
this.groupBoxController.Controls.Add(this.btnAddController);
this.groupBoxController.Controls.Add(this.labelType);
this.groupBoxController.Controls.Add(this.comboBoxType);
this.groupBoxController.Controls.Add(this.labelControllerIndex);
this.groupBoxController.Controls.Add(this.textBoxControllerIndex);
this.groupBoxController.Controls.Add(this.labelPort);
this.groupBoxController.Controls.Add(this.textBoxPort);
this.groupBoxController.Controls.Add(this.labelIp);
this.groupBoxController.Controls.Add(this.textBoxIp);
this.groupBoxController.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.groupBoxController.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(68)))), ((int)(((byte)(68)))), ((int)(((byte)(68)))));
this.groupBoxController.Location = new System.Drawing.Point(15, 360);
this.groupBoxController.Name = "groupBoxController";
this.groupBoxController.Padding = new System.Windows.Forms.Padding(12, 10, 12, 12);
this.groupBoxController.Size = new System.Drawing.Size(450, 250);
this.groupBoxController.TabIndex = 1;
this.groupBoxController.TabStop = false;
this.groupBoxController.Text = "门控制器信息";
//
// btnSaveController
//
this.btnSaveController.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(122)))), ((int)(((byte)(204)))));
this.btnSaveController.FlatAppearance.BorderSize = 0;
this.btnSaveController.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(92)))), ((int)(((byte)(153)))));
this.btnSaveController.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(102)))), ((int)(((byte)(170)))));
this.btnSaveController.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnSaveController.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnSaveController.ForeColor = System.Drawing.Color.White;
this.btnSaveController.Location = new System.Drawing.Point(330, 200);
this.btnSaveController.Name = "btnSaveController";
this.btnSaveController.Size = new System.Drawing.Size(100, 38);
this.btnSaveController.TabIndex = 10;
this.btnSaveController.Text = "保存";
this.btnSaveController.UseVisualStyleBackColor = false;
this.btnSaveController.Click += new System.EventHandler(this.btnSaveController_Click);
//
// btnDeleteController
//
this.btnDeleteController.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(53)))), ((int)(((byte)(69)))));
this.btnDeleteController.FlatAppearance.BorderSize = 0;
this.btnDeleteController.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(165)))), ((int)(((byte)(40)))), ((int)(((byte)(52)))));
this.btnDeleteController.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(187)))), ((int)(((byte)(45)))), ((int)(((byte)(59)))));
this.btnDeleteController.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnDeleteController.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnDeleteController.ForeColor = System.Drawing.Color.White;
this.btnDeleteController.Location = new System.Drawing.Point(220, 200);
this.btnDeleteController.Name = "btnDeleteController";
this.btnDeleteController.Size = new System.Drawing.Size(100, 38);
this.btnDeleteController.TabIndex = 9;
this.btnDeleteController.Text = "删除";
this.btnDeleteController.UseVisualStyleBackColor = false;
this.btnDeleteController.Click += new System.EventHandler(this.btnDeleteController_Click);
//
// btnAddController
//
this.btnAddController.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(167)))), ((int)(((byte)(69)))));
this.btnAddController.FlatAppearance.BorderSize = 0;
this.btnAddController.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(125)))), ((int)(((byte)(52)))));
this.btnAddController.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(33)))), ((int)(((byte)(136)))), ((int)(((byte)(56)))));
this.btnAddController.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnAddController.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnAddController.ForeColor = System.Drawing.Color.White;
this.btnAddController.Location = new System.Drawing.Point(110, 200);
this.btnAddController.Name = "btnAddController";
this.btnAddController.Size = new System.Drawing.Size(100, 38);
this.btnAddController.TabIndex = 8;
this.btnAddController.Text = "添加";
this.btnAddController.UseVisualStyleBackColor = false;
this.btnAddController.Click += new System.EventHandler(this.btnAddController_Click);
//
// labelType
//
this.labelType.AutoSize = true;
this.labelType.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelType.Location = new System.Drawing.Point(28, 168);
this.labelType.Name = "labelType";
this.labelType.Size = new System.Drawing.Size(65, 24);
this.labelType.TabIndex = 7;
this.labelType.Text = "类型:";
//
// comboBoxType
//
this.comboBoxType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxType.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.comboBoxType.FormattingEnabled = true;
this.comboBoxType.Location = new System.Drawing.Point(110, 165);
this.comboBoxType.Name = "comboBoxType";
this.comboBoxType.Size = new System.Drawing.Size(320, 32);
this.comboBoxType.TabIndex = 6;
//
// labelControllerIndex
//
this.labelControllerIndex.AutoSize = true;
this.labelControllerIndex.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelControllerIndex.Location = new System.Drawing.Point(28, 48);
this.labelControllerIndex.Name = "labelControllerIndex";
this.labelControllerIndex.Size = new System.Drawing.Size(65, 24);
this.labelControllerIndex.TabIndex = 1;
this.labelControllerIndex.Text = "编码:";
//
// textBoxControllerIndex
//
this.textBoxControllerIndex.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxControllerIndex.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxControllerIndex.Location = new System.Drawing.Point(110, 45);
this.textBoxControllerIndex.Name = "textBoxControllerIndex";
this.textBoxControllerIndex.Size = new System.Drawing.Size(320, 30);
this.textBoxControllerIndex.TabIndex = 0;
//
// labelIp
//
this.labelIp.AutoSize = true;
this.labelIp.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelIp.Location = new System.Drawing.Point(18, 88);
this.labelIp.Name = "labelIp";
this.labelIp.Size = new System.Drawing.Size(85, 24);
this.labelIp.TabIndex = 3;
this.labelIp.Text = "IP地址:";
//
// textBoxIp
//
this.textBoxIp.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxIp.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxIp.Location = new System.Drawing.Point(110, 85);
this.textBoxIp.Name = "textBoxIp";
this.textBoxIp.Size = new System.Drawing.Size(320, 30);
this.textBoxIp.TabIndex = 2;
this.textBoxIp.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))));
//
// labelPort
//
this.labelPort.AutoSize = true;
this.labelPort.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelPort.Location = new System.Drawing.Point(28, 128);
this.labelPort.Name = "labelPort";
this.labelPort.Size = new System.Drawing.Size(65, 24);
this.labelPort.TabIndex = 5;
this.labelPort.Text = "端口:";
//
// textBoxPort
//
this.textBoxPort.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxPort.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxPort.Location = new System.Drawing.Point(110, 125);
this.textBoxPort.Name = "textBoxPort";
this.textBoxPort.Size = new System.Drawing.Size(320, 30);
this.textBoxPort.TabIndex = 4;
//
// doorListView
//
this.doorListView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.doorListView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.doorListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeaderDoorIndex,
this.columnHeaderControlAddress,
this.columnHeaderOpenStatusAddress});
this.doorListView.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.doorListView.FullRowSelect = true;
this.doorListView.GridLines = true;
this.doorListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.doorListView.HideSelection = false;
this.doorListView.Location = new System.Drawing.Point(483, 55);
this.doorListView.MultiSelect = false;
this.doorListView.Name = "doorListView";
this.doorListView.OwnerDraw = true;
this.doorListView.Size = new System.Drawing.Size(500, 290);
this.doorListView.TabIndex = 2;
this.doorListView.UseCompatibleStateImageBehavior = false;
this.doorListView.View = System.Windows.Forms.View.Details;
this.doorListView.SelectedIndexChanged += new System.EventHandler(this.doorListView_SelectedIndexChanged);
//
// columnHeaderDoorIndex
//
this.columnHeaderDoorIndex.Text = "编码";
this.columnHeaderDoorIndex.Width = 100;
//
// columnHeaderControlAddress
//
this.columnHeaderControlAddress.Text = "控制地址";
this.columnHeaderControlAddress.Width = 180;
//
// columnHeaderOpenStatusAddress
//
this.columnHeaderOpenStatusAddress.Text = "开到位地址";
this.columnHeaderOpenStatusAddress.Width = 180;
//
// groupBoxDoor
//
this.groupBoxDoor.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.checkBoxNoControl = new System.Windows.Forms.CheckBox();
this.groupBoxDoor.Controls.Add(this.checkBoxNoControl);
this.groupBoxDoor.Controls.Add(this.btnSaveDoor);
this.groupBoxDoor.Controls.Add(this.btnDeleteDoor);
this.groupBoxDoor.Controls.Add(this.btnAddDoor);
this.groupBoxDoor.Controls.Add(this.labelOpenStatusAddress);
this.groupBoxDoor.Controls.Add(this.textBoxOpenStatusAddress);
this.groupBoxDoor.Controls.Add(this.labelControlAddress);
this.groupBoxDoor.Controls.Add(this.textBoxControlAddress);
this.groupBoxDoor.Controls.Add(this.labelDoorIndex);
this.groupBoxDoor.Controls.Add(this.textBoxDoorIndex);
this.groupBoxDoor.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.groupBoxDoor.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(68)))), ((int)(((byte)(68)))), ((int)(((byte)(68)))));
this.groupBoxDoor.Location = new System.Drawing.Point(483, 360);
this.groupBoxDoor.Name = "groupBoxDoor";
this.groupBoxDoor.Padding = new System.Windows.Forms.Padding(12, 10, 12, 12);
this.groupBoxDoor.Size = new System.Drawing.Size(500, 250);
this.groupBoxDoor.TabIndex = 3;
this.groupBoxDoor.TabStop = false;
this.groupBoxDoor.Text = "门信息";
//
// btnSaveDoor
//
this.btnSaveDoor.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(122)))), ((int)(((byte)(204)))));
this.btnSaveDoor.FlatAppearance.BorderSize = 0;
this.btnSaveDoor.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(92)))), ((int)(((byte)(153)))));
this.btnSaveDoor.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(102)))), ((int)(((byte)(170)))));
this.btnSaveDoor.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnSaveDoor.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnSaveDoor.ForeColor = System.Drawing.Color.White;
this.btnSaveDoor.Location = new System.Drawing.Point(380, 200);
this.btnSaveDoor.Name = "btnSaveDoor";
this.btnSaveDoor.Size = new System.Drawing.Size(100, 38);
this.btnSaveDoor.TabIndex = 7;
this.btnSaveDoor.Text = "保存";
this.btnSaveDoor.UseVisualStyleBackColor = false;
this.btnSaveDoor.Click += new System.EventHandler(this.btnSaveDoor_Click);
//
// btnDeleteDoor
//
this.btnDeleteDoor.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(53)))), ((int)(((byte)(69)))));
this.btnDeleteDoor.FlatAppearance.BorderSize = 0;
this.btnDeleteDoor.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(165)))), ((int)(((byte)(40)))), ((int)(((byte)(52)))));
this.btnDeleteDoor.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(187)))), ((int)(((byte)(45)))), ((int)(((byte)(59)))));
this.btnDeleteDoor.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnDeleteDoor.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnDeleteDoor.ForeColor = System.Drawing.Color.White;
this.btnDeleteDoor.Location = new System.Drawing.Point(270, 200);
this.btnDeleteDoor.Name = "btnDeleteDoor";
this.btnDeleteDoor.Size = new System.Drawing.Size(100, 38);
this.btnDeleteDoor.TabIndex = 6;
this.btnDeleteDoor.Text = "删除";
this.btnDeleteDoor.UseVisualStyleBackColor = false;
this.btnDeleteDoor.Click += new System.EventHandler(this.btnDeleteDoor_Click);
//
// btnAddDoor
//
this.btnAddDoor.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(167)))), ((int)(((byte)(69)))));
this.btnAddDoor.FlatAppearance.BorderSize = 0;
this.btnAddDoor.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(125)))), ((int)(((byte)(52)))));
this.btnAddDoor.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(33)))), ((int)(((byte)(136)))), ((int)(((byte)(56)))));
this.btnAddDoor.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnAddDoor.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnAddDoor.ForeColor = System.Drawing.Color.White;
this.btnAddDoor.Location = new System.Drawing.Point(160, 200);
this.btnAddDoor.Name = "btnAddDoor";
this.btnAddDoor.Size = new System.Drawing.Size(100, 38);
this.btnAddDoor.TabIndex = 5;
this.btnAddDoor.Text = "添加";
this.btnAddDoor.UseVisualStyleBackColor = false;
this.btnAddDoor.Click += new System.EventHandler(this.btnAddDoor_Click);
//
// labelOpenStatusAddress
//
this.labelOpenStatusAddress.AutoSize = true;
this.labelOpenStatusAddress.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelOpenStatusAddress.Location = new System.Drawing.Point(18, 128);
this.labelOpenStatusAddress.Name = "labelOpenStatusAddress";
this.labelOpenStatusAddress.Size = new System.Drawing.Size(103, 24);
this.labelOpenStatusAddress.TabIndex = 4;
this.labelOpenStatusAddress.Text = "开到位地址:";
//
// textBoxOpenStatusAddress
//
this.textBoxOpenStatusAddress.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxOpenStatusAddress.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxOpenStatusAddress.Location = new System.Drawing.Point(150, 125);
this.textBoxOpenStatusAddress.Name = "textBoxOpenStatusAddress";
this.textBoxOpenStatusAddress.Size = new System.Drawing.Size(330, 30);
this.textBoxOpenStatusAddress.TabIndex = 3;
//
// checkBoxNoControl
//
this.checkBoxNoControl.AutoSize = true;
this.checkBoxNoControl.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.checkBoxNoControl.Location = new System.Drawing.Point(150, 165);
this.checkBoxNoControl.Name = "checkBoxNoControl";
this.checkBoxNoControl.Size = new System.Drawing.Size(162, 28);
this.checkBoxNoControl.TabIndex = 4;
this.checkBoxNoControl.Text = "禁止门控发送指令";
this.checkBoxNoControl.UseVisualStyleBackColor = true;
//
// labelControlAddress
//
this.labelControlAddress.AutoSize = true;
this.labelControlAddress.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelControlAddress.Location = new System.Drawing.Point(18, 88);
this.labelControlAddress.Name = "labelControlAddress";
this.labelControlAddress.Size = new System.Drawing.Size(103, 24);
this.labelControlAddress.TabIndex = 2;
this.labelControlAddress.Text = "控制地址:";
//
// textBoxControlAddress
//
this.textBoxControlAddress.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxControlAddress.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxControlAddress.Location = new System.Drawing.Point(150, 85);
this.textBoxControlAddress.Name = "textBoxControlAddress";
this.textBoxControlAddress.Size = new System.Drawing.Size(330, 30);
this.textBoxControlAddress.TabIndex = 1;
//
// labelDoorIndex
//
this.labelDoorIndex.AutoSize = true;
this.labelDoorIndex.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelDoorIndex.Location = new System.Drawing.Point(28, 48);
this.labelDoorIndex.Name = "labelDoorIndex";
this.labelDoorIndex.Size = new System.Drawing.Size(65, 24);
this.labelDoorIndex.TabIndex = 0;
this.labelDoorIndex.Text = "编码:";
//
// textBoxDoorIndex
//
this.textBoxDoorIndex.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBoxDoorIndex.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.textBoxDoorIndex.Location = new System.Drawing.Point(150, 45);
this.textBoxDoorIndex.Name = "textBoxDoorIndex";
this.textBoxDoorIndex.Size = new System.Drawing.Size(330, 30);
this.textBoxDoorIndex.TabIndex = 0;
//
// labelTitle
//
this.labelTitle.AutoSize = true;
this.labelTitle.Font = new System.Drawing.Font("微软雅黑", 16F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelTitle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(51)))), ((int)(((byte)(51)))), ((int)(((byte)(51)))));
this.labelTitle.Location = new System.Drawing.Point(15, 12);
this.labelTitle.Name = "labelTitle";
this.labelTitle.Size = new System.Drawing.Size(150, 42);
this.labelTitle.TabIndex = 4;
this.labelTitle.Text = "门控制器管理";
//
// DoorManager
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(245)))), ((int)(((byte)(245)))), ((int)(((byte)(247)))));
this.ClientSize = new System.Drawing.Size(1000, 620);
this.Controls.Add(this.labelTitle);
this.Controls.Add(this.groupBoxDoor);
this.Controls.Add(this.doorListView);
this.Controls.Add(this.groupBoxController);
this.Controls.Add(this.doorControllerListView);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.MinimumSize = new System.Drawing.Size(1000, 620);
this.Name = "DoorManager";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "门控制器管理";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.DoorManager_FormClosing);
this.Load += new System.EventHandler(this.DoorManager_Load);
this.groupBoxController.ResumeLayout(false);
this.groupBoxController.PerformLayout();
this.groupBoxDoor.ResumeLayout(false);
this.groupBoxDoor.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ListView doorControllerListView;
private System.Windows.Forms.ColumnHeader columnHeaderControllerIndex;
private System.Windows.Forms.ColumnHeader columnHeaderIp;
private System.Windows.Forms.ColumnHeader columnHeaderPort;
private System.Windows.Forms.ColumnHeader columnHeaderType;
private System.Windows.Forms.GroupBox groupBoxController;
private System.Windows.Forms.TextBox textBoxIp;
private System.Windows.Forms.Label labelIp;
private System.Windows.Forms.Label labelPort;
private System.Windows.Forms.TextBox textBoxPort;
private System.Windows.Forms.Label labelControllerIndex;
private System.Windows.Forms.TextBox textBoxControllerIndex;
private System.Windows.Forms.Label labelType;
private System.Windows.Forms.ComboBox comboBoxType;
private System.Windows.Forms.Button btnAddController;
private System.Windows.Forms.Button btnDeleteController;
private System.Windows.Forms.Button btnSaveController;
private System.Windows.Forms.ListView doorListView;
private System.Windows.Forms.ColumnHeader columnHeaderDoorIndex;
private System.Windows.Forms.ColumnHeader columnHeaderControlAddress;
private System.Windows.Forms.ColumnHeader columnHeaderOpenStatusAddress;
private System.Windows.Forms.GroupBox groupBoxDoor;
private System.Windows.Forms.Label labelDoorIndex;
private System.Windows.Forms.TextBox textBoxDoorIndex;
private System.Windows.Forms.Label labelControlAddress;
private System.Windows.Forms.TextBox textBoxControlAddress;
private System.Windows.Forms.Label labelOpenStatusAddress;
private System.Windows.Forms.TextBox textBoxOpenStatusAddress;
private System.Windows.Forms.Button btnAddDoor;
private System.Windows.Forms.Button btnDeleteDoor;
private System.Windows.Forms.Button btnSaveDoor;
private System.Windows.Forms.Label labelTitle;
private System.Windows.Forms.CheckBox checkBoxNoControl;
}
}
File diff suppressed because it is too large Load Diff
@@ -1,64 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<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="timerRefresh.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>
@@ -1013,29 +1013,11 @@ namespace StandardScene.ExtendDevice.Door
{
try
{
var monitor = DoorMonitor.Instance;
if (monitor.Visible)
{
if (monitor.WindowState == System.Windows.Forms.FormWindowState.Minimized)
{
monitor.WindowState = System.Windows.Forms.FormWindowState.Normal;
}
monitor.Activate();
monitor.BringToFront();
}
else
{
monitor.Show();
monitor.Activate();
}
monitor.EnsureRefreshActive();
DoorMonitor.Open();
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show($"打开门控监控界面失败: {ex.Message}", "错误",
System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
CycleUiHelper.Alert("错误", $"打开门控监控界面失败: {ex.Message}");
}
}
}
@@ -1,263 +0,0 @@
namespace StandardScene.ExtendDevice.Door
{
partial class DoorMonitor
{
/// <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()
{
this.doorListView = new System.Windows.Forms.ListView();
this.columnHeaderControllerIndex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderDoorIndex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderState = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderTarget = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderSource = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderManualRemain = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderCarsInArea = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderControlAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeaderOpenStatusAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.groupBoxControl = new System.Windows.Forms.GroupBox();
this.btnClose = new System.Windows.Forms.Button();
this.btnOpen = new System.Windows.Forms.Button();
this.btnClearCars = new System.Windows.Forms.Button();
this.labelDoorInfo = new System.Windows.Forms.Label();
this.labelTitle = new System.Windows.Forms.Label();
this.timerRefresh = new System.Windows.Forms.Timer();
this.groupBoxControl.SuspendLayout();
this.SuspendLayout();
//
// doorListView
//
this.doorListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.doorListView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.doorListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeaderControllerIndex,
this.columnHeaderDoorIndex,
this.columnHeaderState,
this.columnHeaderTarget,
this.columnHeaderSource,
this.columnHeaderManualRemain,
this.columnHeaderCarsInArea,
this.columnHeaderControlAddress,
this.columnHeaderOpenStatusAddress});
this.doorListView.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.doorListView.FullRowSelect = true;
this.doorListView.GridLines = true;
this.doorListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.doorListView.HideSelection = false;
this.doorListView.Location = new System.Drawing.Point(15, 55);
this.doorListView.MultiSelect = false;
this.doorListView.Name = "doorListView";
this.doorListView.OwnerDraw = true;
this.doorListView.Size = new System.Drawing.Size(800, 400);
this.doorListView.TabIndex = 0;
this.doorListView.UseCompatibleStateImageBehavior = false;
this.doorListView.View = System.Windows.Forms.View.Details;
this.doorListView.SelectedIndexChanged += new System.EventHandler(this.doorListView_SelectedIndexChanged);
//
// columnHeaderControllerIndex
//
this.columnHeaderControllerIndex.Text = "控制器编码";
this.columnHeaderControllerIndex.Width = 120;
//
// columnHeaderDoorIndex
//
this.columnHeaderDoorIndex.Text = "门编码";
this.columnHeaderDoorIndex.Width = 100;
//
// columnHeaderState
//
this.columnHeaderState.Text = "状态";
this.columnHeaderState.Width = 100;
//
// columnHeaderTarget
//
this.columnHeaderTarget.Text = "控制目标";
this.columnHeaderTarget.Width = 100;
//
// columnHeaderSource
//
this.columnHeaderSource.Text = "控制来源";
this.columnHeaderSource.Width = 100;
//
// columnHeaderManualRemain
//
this.columnHeaderManualRemain.Text = "手动剩余(s)";
this.columnHeaderManualRemain.Width = 110;
//
// columnHeaderCarsInArea
//
this.columnHeaderCarsInArea.Text = "车辆占用";
this.columnHeaderCarsInArea.Width = 150;
//
// columnHeaderControlAddress
//
this.columnHeaderControlAddress.Text = "控制地址";
this.columnHeaderControlAddress.Width = 120;
//
// columnHeaderOpenStatusAddress
//
this.columnHeaderOpenStatusAddress.Text = "开到位地址";
this.columnHeaderOpenStatusAddress.Width = 120;
//
// groupBoxControl
//
this.groupBoxControl.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBoxControl.Controls.Add(this.btnClose);
this.groupBoxControl.Controls.Add(this.btnOpen);
this.groupBoxControl.Controls.Add(this.btnClearCars);
this.groupBoxControl.Controls.Add(this.labelDoorInfo);
this.groupBoxControl.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.groupBoxControl.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(68)))), ((int)(((byte)(68)))), ((int)(((byte)(68)))));
this.groupBoxControl.Location = new System.Drawing.Point(15, 470);
this.groupBoxControl.Name = "groupBoxControl";
this.groupBoxControl.Padding = new System.Windows.Forms.Padding(12, 10, 12, 12);
this.groupBoxControl.Size = new System.Drawing.Size(800, 120);
this.groupBoxControl.TabIndex = 1;
this.groupBoxControl.TabStop = false;
this.groupBoxControl.Text = "手动控制";
//
// btnClose
//
this.btnClose.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(53)))), ((int)(((byte)(69)))));
this.btnClose.FlatAppearance.BorderSize = 0;
this.btnClose.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(165)))), ((int)(((byte)(40)))), ((int)(((byte)(52)))));
this.btnClose.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(187)))), ((int)(((byte)(45)))), ((int)(((byte)(59)))));
this.btnClose.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnClose.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnClose.ForeColor = System.Drawing.Color.White;
this.btnClose.Location = new System.Drawing.Point(450, 50);
this.btnClose.Name = "btnClose";
this.btnClose.Size = new System.Drawing.Size(120, 50);
this.btnClose.TabIndex = 2;
this.btnClose.Text = "关闭";
this.btnClose.UseVisualStyleBackColor = false;
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
//
// btnOpen
//
this.btnOpen.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(167)))), ((int)(((byte)(69)))));
this.btnOpen.FlatAppearance.BorderSize = 0;
this.btnOpen.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(125)))), ((int)(((byte)(52)))));
this.btnOpen.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(33)))), ((int)(((byte)(136)))), ((int)(((byte)(56)))));
this.btnOpen.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnOpen.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnOpen.ForeColor = System.Drawing.Color.White;
this.btnOpen.Location = new System.Drawing.Point(300, 50);
this.btnOpen.Name = "btnOpen";
this.btnOpen.Size = new System.Drawing.Size(120, 50);
this.btnOpen.TabIndex = 1;
this.btnOpen.Text = "打开";
this.btnOpen.UseVisualStyleBackColor = false;
this.btnOpen.Click += new System.EventHandler(this.btnOpen_Click);
//
// btnClearCars
//
this.btnClearCars.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(108)))), ((int)(((byte)(117)))), ((int)(((byte)(125)))));
this.btnClearCars.FlatAppearance.BorderSize = 0;
this.btnClearCars.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnClearCars.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnClearCars.ForeColor = System.Drawing.Color.White;
this.btnClearCars.Location = new System.Drawing.Point(600, 50);
this.btnClearCars.Name = "btnClearCars";
this.btnClearCars.Size = new System.Drawing.Size(140, 50);
this.btnClearCars.TabIndex = 3;
this.btnClearCars.Text = "清空占用";
this.btnClearCars.UseVisualStyleBackColor = false;
this.btnClearCars.Click += new System.EventHandler(this.btnClearCars_Click);
//
// labelDoorInfo
//
this.labelDoorInfo.AutoSize = true;
this.labelDoorInfo.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelDoorInfo.Location = new System.Drawing.Point(20, 35);
this.labelDoorInfo.Name = "labelDoorInfo";
this.labelDoorInfo.Size = new System.Drawing.Size(200, 24);
this.labelDoorInfo.TabIndex = 0;
this.labelDoorInfo.Text = "请选择要控制的门";
//
// labelTitle
//
this.labelTitle.AutoSize = true;
this.labelTitle.Font = new System.Drawing.Font("微软雅黑", 16F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.labelTitle.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(51)))), ((int)(((byte)(51)))), ((int)(((byte)(51)))));
this.labelTitle.Location = new System.Drawing.Point(15, 12);
this.labelTitle.Name = "labelTitle";
this.labelTitle.Size = new System.Drawing.Size(150, 42);
this.labelTitle.TabIndex = 2;
this.labelTitle.Text = "门控监控";
//
// timerRefresh
//
this.timerRefresh.Interval = 1000;
this.timerRefresh.Tick += new System.EventHandler(this.timerRefresh_Tick);
//
// DoorMonitor
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(245)))), ((int)(((byte)(245)))), ((int)(((byte)(247)))));
this.ClientSize = new System.Drawing.Size(830, 600);
this.Controls.Add(this.labelTitle);
this.Controls.Add(this.groupBoxControl);
this.Controls.Add(this.doorListView);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.MinimumSize = new System.Drawing.Size(830, 600);
this.Name = "DoorMonitor";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "门控监控";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.DoorMonitor_FormClosing);
this.Load += new System.EventHandler(this.DoorMonitor_Load);
this.groupBoxControl.ResumeLayout(false);
this.groupBoxControl.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ListView doorListView;
private System.Windows.Forms.ColumnHeader columnHeaderControllerIndex;
private System.Windows.Forms.ColumnHeader columnHeaderDoorIndex;
private System.Windows.Forms.ColumnHeader columnHeaderState;
private System.Windows.Forms.ColumnHeader columnHeaderTarget;
private System.Windows.Forms.ColumnHeader columnHeaderSource;
private System.Windows.Forms.ColumnHeader columnHeaderManualRemain;
private System.Windows.Forms.ColumnHeader columnHeaderCarsInArea;
private System.Windows.Forms.ColumnHeader columnHeaderControlAddress;
private System.Windows.Forms.ColumnHeader columnHeaderOpenStatusAddress;
private System.Windows.Forms.GroupBox groupBoxControl;
private System.Windows.Forms.Label labelDoorInfo;
private System.Windows.Forms.Button btnOpen;
private System.Windows.Forms.Button btnClose;
private System.Windows.Forms.Button btnClearCars;
private System.Windows.Forms.Label labelTitle;
private System.Windows.Forms.Timer timerRefresh;
}
}
@@ -2,445 +2,241 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using CycleGUI;
using SimpleLite;
using StandardScene.Utils;
namespace StandardScene.ExtendDevice.Door
{
public partial class DoorMonitor : Form
/// <summary>
/// 门控监控界面(CycleGUI 版,替代原 WinForms <c>DoorMonitor</c> 窗体)。
/// <list type="bullet">
/// <item>单实例:再次打开则把已有面板置前。</item>
/// <item><c>pb.Table</c> 展示门列表,单击行选中以进行手动控制。</item>
/// <item>约每 500ms 重绘刷新门状态快照(替代 WinForms 定时器)。</item>
/// </list>
/// </summary>
public class DoorMonitor
{
private static DoorMonitor _instance = null;
private static readonly object _lock = new object();
private const string TableId = "door-monitor-list";
private int _doorHoverIndex = -1;
private (int ControllerIndex, int DoorIndex)? _selectedDoor = null;
private static readonly Color SelectedRowColor = Color.FromArgb(230, 240, 255);
private static readonly Color RowEvenColor = Color.FromArgb(250, 250, 252);
private static readonly Color RowOddColor = Color.White;
private static readonly Color RowHighlightColor = Color.FromArgb(230, 240, 255);
private static readonly Color TextRegularColor = Color.FromArgb(68, 68, 68);
private static readonly Color TextHighlightColor = Color.FromArgb(51, 51, 51);
private static readonly Color StateOpenColor = Color.FromArgb(40, 167, 69);
private static readonly Color StateClosedColor = Color.FromArgb(220, 53, 69);
private static Panel _panel;
private static (int ControllerIndex, int DoorIndex)? _selectedDoor;
/// <summary>
/// 获取单例实例
/// </summary>
public static DoorMonitor Instance
/// <summary>打开(或置前)门控监控面板。</summary>
public static void Open()
{
get
if (_panel != null)
{
if (_instance == null || _instance.IsDisposed)
try
{
lock (_lock)
{
if (_instance == null || _instance.IsDisposed)
{
_instance = new DoorMonitor();
}
}
_panel.BringToFront();
return;
}
return _instance;
}
}
/// <summary>
/// 私有构造函数,确保单例模式
/// </summary>
private DoorMonitor()
{
InitializeComponent();
}
/// <summary>
/// 确保刷新定时器处于激活状态,并立即刷新一次
/// </summary>
public void EnsureRefreshActive()
{
if (IsDisposed)
{
return;
}
if (!timerRefresh.Enabled)
{
timerRefresh.Start();
}
RefreshDoorList();
}
private void DoorMonitor_Load(object sender, EventArgs e)
{
SetupListViewStyles();
// 禁用系统的悬停/热跟踪高亮,避免鼠标移动时短暂出现默认遮罩
doorListView.HoverSelection = false;
doorListView.HotTracking = false;
EnsureRefreshActive();
}
/// <summary>
/// 设置ListView的视觉样式
/// </summary>
private void SetupListViewStyles()
{
doorListView.OwnerDraw = true;
doorListView.BackColor = Color.White;
doorListView.DrawItem += DoorListView_DrawItem;
doorListView.DrawSubItem += DoorListView_DrawSubItem;
doorListView.DrawColumnHeader += DoorListView_DrawColumnHeader;
doorListView.MouseMove += DoorListView_MouseMove;
doorListView.MouseLeave += DoorListView_MouseLeave;
// 启用双缓冲
typeof(Control)?.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic)?
.SetValue(doorListView, true, null);
}
private void DoorListView_MouseMove(object sender, MouseEventArgs e)
{
var hoveredItem = doorListView.GetItemAt(e.X, e.Y);
int newIndex = hoveredItem?.Index ?? -1;
if (_doorHoverIndex != newIndex)
{
_doorHoverIndex = newIndex;
doorListView.Invalidate();
}
}
private void DoorListView_MouseLeave(object sender, EventArgs e)
{
if (_doorHoverIndex != -1)
{
_doorHoverIndex = -1;
doorListView.Invalidate();
}
}
private void DoorListView_DrawItem(object sender, DrawListViewItemEventArgs e)
{
var isHighlighted = e.Item.Selected
|| e.ItemIndex == _doorHoverIndex
|| (doorListView.Focused && (e.State & ListViewItemStates.Focused) != 0);
var backColor = isHighlighted
? RowHighlightColor
: (e.ItemIndex % 2 == 0 ? RowEvenColor : RowOddColor);
using (var brush = new SolidBrush(backColor))
{
e.Graphics.FillRectangle(brush, e.Bounds);
}
var textColor = isHighlighted ? TextHighlightColor : TextRegularColor;
TextRenderer.DrawText(e.Graphics, e.Item.Text, e.Item.Font, e.Bounds,
textColor,
TextFormatFlags.VerticalCenter | TextFormatFlags.Left | TextFormatFlags.EndEllipsis);
e.DrawFocusRectangle();
}
private void DoorListView_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
var isHighlighted = e.Item.Selected
|| e.ItemIndex == _doorHoverIndex
|| (doorListView.Focused && (e.ItemState & ListViewItemStates.Focused) != 0);
var backColor = isHighlighted
? RowHighlightColor
: (e.ItemIndex % 2 == 0 ? RowEvenColor : RowOddColor);
using (var brush = new SolidBrush(backColor))
{
e.Graphics.FillRectangle(brush, e.Bounds);
}
Color textColor = TextRegularColor;
// 如果是状态列,根据状态设置颜色
if (e.ColumnIndex == 2) // 状态列
{
var stateText = e.SubItem.Text;
if (stateText == "打开")
catch
{
textColor = StateOpenColor;
}
else if (stateText == "关闭")
{
textColor = StateClosedColor;
}
}
// 如果是目标控制列,按目标状态着色
else if (e.ColumnIndex == 3) // 控制目标列
{
var targetText = e.SubItem.Text;
if (targetText == "开")
{
textColor = StateOpenColor;
}
else
{
textColor = StateClosedColor;
}
}
// 其他列使用默认颜色
else
{
textColor = isHighlighted ? TextHighlightColor : TextRegularColor;
}
TextRenderer.DrawText(e.Graphics, e.SubItem.Text, e.SubItem.Font, e.Bounds,
textColor,
TextFormatFlags.VerticalCenter | TextFormatFlags.Left | TextFormatFlags.EndEllipsis);
}
private void DoorListView_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(245, 247, 250)), e.Bounds);
e.Graphics.DrawLine(new Pen(Color.FromArgb(220, 220, 220)),
e.Bounds.Left, e.Bounds.Bottom - 1, e.Bounds.Right, e.Bounds.Bottom - 1);
TextRenderer.DrawText(e.Graphics, e.Header.Text,
new Font("微软雅黑", 10.5F, FontStyle.Bold),
e.Bounds, Color.FromArgb(68, 68, 68),
TextFormatFlags.VerticalCenter | TextFormatFlags.Left | TextFormatFlags.HorizontalCenter);
}
/// <summary>
/// 刷新门列表
/// </summary>
private void RefreshDoorList()
{
doorListView.Items.Clear();
// 保存当前选中的门
(int ControllerIndex, int DoorIndex)? previousSelected = _selectedDoor;
_selectedDoor = null;
labelDoorInfo.Text = "请选择要控制的门";
// 获取所有门控制器
var mission = SimpleProject.proj?.Missions?.OfType<DoorMission>().FirstOrDefault();
if (mission == null)
{
return;
}
var doorSnapshot = mission.GetDoorMonitorSnapshot();
if (doorSnapshot.Count == 0)
{
return;
}
ListViewItem selectedItem = null;
foreach (var door in doorSnapshot)
{
var stateText = door.State == DoorState.Open ? "打开" : door.State == DoorState.Closed ? "关闭" : "未知";
var targetText = door.Target ? "开" : "关";
var sourceText = door.Source == DoorMission.ControlSource.Manual ? "手动" : "自动";
var remainText = door.Source == DoorMission.ControlSource.Manual && door.ManualRemainingSeconds.HasValue
? Math.Ceiling(door.ManualRemainingSeconds.Value).ToString()
: "-";
var carsText = door.CarsInArea.Count > 0 ? string.Join(", ", door.CarsInArea) : "无";
var item = new ListViewItem(door.ControllerIndex.ToString());
item.SubItems.Add(door.DoorIndex.ToString());
item.SubItems.Add(stateText);
item.SubItems.Add(targetText);
item.SubItems.Add(sourceText);
item.SubItems.Add(remainText);
item.SubItems.Add(carsText);
item.SubItems.Add(door.ControlAddress.ToString());
item.SubItems.Add(door.OpenStatusAddress.ToString());
item.Tag = (door.ControllerIndex, door.DoorIndex);
item.UseItemStyleForSubItems = false;
doorListView.Items.Add(item);
// 如果之前选中的门存在,恢复选中状态
if (previousSelected.HasValue &&
previousSelected.Value.ControllerIndex == door.ControllerIndex &&
previousSelected.Value.DoorIndex == door.DoorIndex)
{
selectedItem = item;
_panel = null;
}
}
// 恢复选中状态
if (selectedItem != null)
{
selectedItem.Selected = true;
selectedItem.EnsureVisible();
doorListView_SelectedIndexChanged(doorListView, EventArgs.Empty);
}
}
var panel = GUI.DeclarePanel()
.ShowTitle("门控监控")
.SetDefaultDocking(Panel.Docking.None)
.InitSize(1200, 620)
.InitPos(false, 0, 0, 0.5f, 0.5f, 0.5f, 0.5f);
_panel = panel;
panel.IfTerminalQuit(() => _panel = null);
/// <summary>
/// 门列表选择改变
/// </summary>
private void doorListView_SelectedIndexChanged(object sender, EventArgs e)
{
if (doorListView.SelectedItems.Count > 0)
panel.Define(pb =>
{
var tag = doorListView.SelectedItems[0].Tag;
if (tag != null && tag is ValueTuple<int, int>)
{
var doorInfo = (ValueTuple<int, int>)tag;
_selectedDoor = doorInfo;
labelDoorInfo.Text = $"控制器编码: {doorInfo.Item1}, 门编码: {doorInfo.Item2}";
// 根据占用状态决定关闭按钮是否可用
var mission = SimpleProject.proj?.Missions?.OfType<DoorMission>().FirstOrDefault();
var carsInArea = mission?.GetCarsInArea(doorInfo.Item1, doorInfo.Item2) ?? Array.Empty<int>();
btnClose.Enabled = carsInArea.Count == 0;
}
else
if (pb.Closing())
{
panel.Exit();
_panel = null;
_selectedDoor = null;
labelDoorInfo.Text = "请选择要控制的门";
btnClose.Enabled = true;
return;
}
}
else
{
_selectedDoor = null;
labelDoorInfo.Text = "请选择要控制的门";
btnClose.Enabled = true;
}
var mission = GetMission();
var snapshot = mission?.GetDoorMonitorSnapshot() ?? Array.Empty<DoorMission.DoorMonitorSnapshotItem>();
pb.Label($"共 {snapshot.Count} 扇门");
pb.Label(GetDoorInfoText(snapshot));
pb.Table(TableId,
new[]
{
"控制器编码", "门编码", "状态", "控制目标", "控制来源",
"手动剩余(s)", "车辆占用", "控制地址", "开到位地址"
},
snapshot.Count, (row, i) =>
{
var door = snapshot[i];
if (IsRowSelected(door))
row.SetColor(SelectedRowColor);
LabelCell(row, door, door.ControllerIndex.ToString());
LabelCell(row, door, door.DoorIndex.ToString());
LabelCell(row, door, FormatState(door.State));
LabelCell(row, door, door.Target ? "开" : "关");
LabelCell(row, door, door.Source == DoorMission.ControlSource.Manual ? "手动" : "自动");
LabelCell(row, door, FormatManualRemain(door));
LabelCell(row, door, FormatCars(door));
LabelCell(row, door, door.ControlAddress.ToString());
LabelCell(row, door, door.OpenStatusAddress.ToString());
}, height: 18, enableSearch: true);
pb.Separator();
pb.Label("手动控制");
var canClose = CanCloseSelected(mission);
if (pb.Button("打开", distinct: "door-monitor-open"))
OpenSelectedDoor();
pb.SameLine(12);
if (pb.Button("关闭", distinct: "door-monitor-close", disabled: !canClose))
CloseSelectedDoor();
pb.SameLine(12);
if (pb.Button("清空占用", distinct: "door-monitor-clear-cars"))
ClearSelectedCars();
pb.Panel.Repaint(repaintTimeMs: 500);
});
}
/// <summary>
/// 打开门
/// </summary>
private void btnOpen_Click(object sender, EventArgs e)
private static void LabelCell(PanelBuilder.Row row, DoorMission.DoorMonitorSnapshotItem door, string text)
{
if (row.Label(text))
_selectedDoor = (door.ControllerIndex, door.DoorIndex);
}
private static DoorMission GetMission() =>
SimpleProject.proj?.Missions?.OfType<DoorMission>().FirstOrDefault();
private static 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)
{
if (!_selectedDoor.HasValue)
return "请选择要控制的门";
var door = snapshot.FirstOrDefault(d =>
d.ControllerIndex == _selectedDoor.Value.ControllerIndex
&& d.DoorIndex == _selectedDoor.Value.DoorIndex);
if (door == null)
return $"控制器编码: {_selectedDoor.Value.ControllerIndex}, 门编码: {_selectedDoor.Value.DoorIndex}";
return $"控制器编码: {door.ControllerIndex}, 门编码: {door.DoorIndex}";
}
private static bool CanCloseSelected(DoorMission mission)
{
if (!_selectedDoor.HasValue || mission == null)
return true;
var cars = mission.GetCarsInArea(_selectedDoor.Value.ControllerIndex, _selectedDoor.Value.DoorIndex);
return cars.Count == 0;
}
private static string FormatState(DoorState state) =>
state == DoorState.Open ? "打开" : state == DoorState.Closed ? "关闭" : "未知";
private static 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) =>
door.CarsInArea.Count > 0 ? string.Join(", ", door.CarsInArea) : "无";
private static void OpenSelectedDoor()
{
if (!_selectedDoor.HasValue)
{
MessageBox.Show("请先选择要控制的门", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
CycleUiHelper.Alert("提示", "请先选择要控制的门");
return;
}
try
{
var mission = SimpleProject.proj?.Missions?.OfType<DoorMission>().FirstOrDefault();
var mission = GetMission();
if (mission == null)
{
MessageBox.Show("未找到门控进程", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
CycleUiHelper.Alert("错误", "未找到门控进程");
return;
}
var (controllerIndex, doorIndex) = _selectedDoor.Value;
// 手动控制:默认保持10秒
mission.SetManualDoorControl(controllerIndex, doorIndex, true);
MessageBox.Show($"控制器 {controllerIndex} 门 {doorIndex} 已设置手动打开(10秒)", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
CycleUiHelper.Alert("提示", $"控制器 {controllerIndex} 门 {doorIndex} 已设置手动打开(10秒)");
}
catch (Exception ex)
{
MessageBox.Show($"设置门打开目标失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
CycleUiHelper.Alert("错误", $"设置门打开目标失败: {ex.Message}");
}
}
/// <summary>
/// 关闭门
/// </summary>
private void btnClose_Click(object sender, EventArgs e)
private static void CloseSelectedDoor()
{
if (!_selectedDoor.HasValue)
{
MessageBox.Show("请先选择要控制的门", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
CycleUiHelper.Alert("提示", "请先选择要控制的门");
return;
}
try
{
var mission = SimpleProject.proj?.Missions?.OfType<DoorMission>().FirstOrDefault();
var mission = GetMission();
if (mission == null)
{
MessageBox.Show("未找到门控进程", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
CycleUiHelper.Alert("错误", "未找到门控进程");
return;
}
var (controllerIndex, doorIndex) = _selectedDoor.Value;
// 车辆占用时禁止手动关闭
var success = mission.SetManualDoorControl(controllerIndex, doorIndex, false);
if (!success)
{
MessageBox.Show("门存在车辆占用,禁止手动关闭。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
CycleUiHelper.Alert("提示", "门存在车辆占用,禁止手动关闭。");
return;
}
MessageBox.Show($"控制器 {controllerIndex} 门 {doorIndex} 已设置手动关闭(10秒)", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
CycleUiHelper.Alert("提示", $"控制器 {controllerIndex} 门 {doorIndex} 已设置手动关闭(10秒)");
}
catch (Exception ex)
{
MessageBox.Show($"设置门关闭目标失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
CycleUiHelper.Alert("错误", $"设置门关闭目标失败: {ex.Message}");
}
}
/// <summary>
/// 清空车辆占用
/// </summary>
private void btnClearCars_Click(object sender, EventArgs e)
private static void ClearSelectedCars()
{
if (!_selectedDoor.HasValue)
{
MessageBox.Show("请先选择要清空占用的门", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
CycleUiHelper.Alert("提示", "请先选择要清空占用的门");
return;
}
try
{
var mission = SimpleProject.proj?.Missions?.OfType<DoorMission>().FirstOrDefault();
var mission = GetMission();
if (mission == null)
{
MessageBox.Show("未找到门控进程", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
CycleUiHelper.Alert("错误", "未找到门控进程");
return;
}
var (controllerIndex, doorIndex) = _selectedDoor.Value;
mission.ClearCarsInArea(controllerIndex, doorIndex);
MessageBox.Show($"控制器 {controllerIndex} 门 {doorIndex} 已清空占用", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
RefreshDoorList();
CycleUiHelper.Alert("提示", $"控制器 {controllerIndex} 门 {doorIndex} 已清空占用");
}
catch (Exception ex)
{
MessageBox.Show($"清空占用失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 定时刷新
/// </summary>
private void timerRefresh_Tick(object sender, EventArgs e)
{
RefreshDoorList();
}
/// <summary>
/// 窗体关闭事件
/// </summary>
private void DoorMonitor_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
timerRefresh.Stop();
e.Cancel = true;
this.Visible = false;
}
}
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
if (Visible)
{
EnsureRefreshActive();
}
else
{
timerRefresh.Stop();
CycleUiHelper.Alert("错误", $"清空占用失败: {ex.Message}");
}
}
}
@@ -1,64 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<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="timerRefresh.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>
@@ -12,7 +12,7 @@ using SimpleLite.CADTools;
using SimpleLite.Props;
using SimpleLite.UI;
using SimpleLite;
using System.Windows.Forms;
using StandardScene.Utils;
using Newtonsoft.Json;
namespace StandardScene.InterLock
@@ -297,7 +297,7 @@ namespace StandardScene.InterLock
var vv = await Program.UI.Input("请输入true/false", title, "true");
if (vv == null || !bool.TryParse(vv, out var allow))
{
MessageBox.Show("输入错误");
CycleUiHelper.Alert("错误", "输入错误");
return;
}
lock (sync) toManipulate[site.id] = allow;
@@ -10,7 +10,6 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
namespace StandardScene.InterLock
{
@@ -60,7 +59,7 @@ namespace StandardScene.InterLock
{
try
{
string ConfigPath = Path.Combine(Application.StartupPath, "Config/traffic.json");
string ConfigPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config", "traffic.json");
if (File.Exists(ConfigPath))
{
@@ -137,6 +136,11 @@ namespace StandardScene.InterLock
public class TrafficArea
{
/// <summary>
/// 区域稳定标识,用于界面编辑/批量删除时避免行索引错位。
/// </summary>
public string Id { get; set; }
/// <summary>
/// 区域名称
/// </summary>
@@ -1,325 +0,0 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace LoopViewerApp
{
partial class TrafficInterlockViewer
{
private System.ComponentModel.IContainer components = null;
private ListView lstTasks;
private GroupBox grpEdit;
private ColumnHeader colAreaName;
private ColumnHeader colSites;
private ColumnHeader colControlRight;
private ColumnHeader colIsOccupied;
private ColumnHeader colIsEnabled;
private Label lblAreaName;
private TextBox txtAreaName;
private Label lblStationIds;
private TextBox txtStationIds;
private Label lblControlRight;
private TextBox txtControlRight;
private Label lblIsOccupied;
private CheckBox chkIsOccupied;
private Label lblIsEnabled;
private CheckBox chkIsEnabled;
private Label lblEditingHint;
private Button btnSave;
private Button btnRefresh;
private Button btnNew;
private Button btnDelete;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.lstTasks = new System.Windows.Forms.ListView();
this.colAreaName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colSites = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colControlRight = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colIsOccupied = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colIsEnabled = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.grpEdit = new System.Windows.Forms.GroupBox();
this.lblEditingHint = new System.Windows.Forms.Label();
this.lblAreaName = new System.Windows.Forms.Label();
this.txtAreaName = new System.Windows.Forms.TextBox();
this.lblStationIds = new System.Windows.Forms.Label();
this.txtStationIds = new System.Windows.Forms.TextBox();
this.lblControlRight = new System.Windows.Forms.Label();
this.txtControlRight = new System.Windows.Forms.TextBox();
this.lblIsOccupied = new System.Windows.Forms.Label();
this.chkIsOccupied = new System.Windows.Forms.CheckBox();
this.lblIsEnabled = new System.Windows.Forms.Label();
this.chkIsEnabled = new System.Windows.Forms.CheckBox();
this.btnSave = new System.Windows.Forms.Button();
this.btnRefresh = new System.Windows.Forms.Button();
this.btnNew = new System.Windows.Forms.Button();
this.btnDelete = new System.Windows.Forms.Button();
this.grpEdit.SuspendLayout();
this.SuspendLayout();
//
// lstTasks
//
this.lstTasks.BackColor = System.Drawing.Color.White;
this.lstTasks.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.colAreaName,
this.colSites,
this.colControlRight,
this.colIsOccupied,
this.colIsEnabled});
this.lstTasks.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(33)))), ((int)(((byte)(33)))), ((int)(((byte)(33)))));
this.lstTasks.FullRowSelect = true;
this.lstTasks.HideSelection = false;
this.lstTasks.Location = new System.Drawing.Point(12, 12);
this.lstTasks.Name = "lstTasks";
this.lstTasks.OwnerDraw = true;
this.lstTasks.Size = new System.Drawing.Size(760, 320);
this.lstTasks.TabIndex = 0;
this.lstTasks.UseCompatibleStateImageBehavior = false;
this.lstTasks.View = System.Windows.Forms.View.Details;
this.lstTasks.DrawColumnHeader += new System.Windows.Forms.DrawListViewColumnHeaderEventHandler(this.lstTasks_DrawColumnHeader);
this.lstTasks.DrawItem += new System.Windows.Forms.DrawListViewItemEventHandler(this.lstTasks_DrawItem);
this.lstTasks.DrawSubItem += new System.Windows.Forms.DrawListViewSubItemEventHandler(this.lstTasks_DrawSubItem);
this.lstTasks.SelectedIndexChanged += new System.EventHandler(this.lstTasks_SelectedIndexChanged);
//
// colAreaName
//
this.colAreaName.Text = "区域名称";
this.colAreaName.Width = 140;
//
// colSites
//
this.colSites.Text = "区域站点集合";
this.colSites.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.colSites.Width = 280;
//
// colControlRight
//
this.colControlRight.Text = "控制权";
this.colControlRight.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.colControlRight.Width = 120;
//
// colIsOccupied
//
this.colIsOccupied.Text = "是否被占用";
this.colIsOccupied.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.colIsOccupied.Width = 100;
//
// colIsEnabled
//
this.colIsEnabled.Text = "是否启用";
this.colIsEnabled.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.colIsEnabled.Width = 100;
//
// grpEdit
//
this.grpEdit.Controls.Add(this.lblEditingHint);
this.grpEdit.Controls.Add(this.lblAreaName);
this.grpEdit.Controls.Add(this.txtAreaName);
this.grpEdit.Controls.Add(this.lblStationIds);
this.grpEdit.Controls.Add(this.txtStationIds);
this.grpEdit.Controls.Add(this.lblControlRight);
this.grpEdit.Controls.Add(this.txtControlRight);
this.grpEdit.Controls.Add(this.lblIsOccupied);
this.grpEdit.Controls.Add(this.chkIsOccupied);
this.grpEdit.Controls.Add(this.lblIsEnabled);
this.grpEdit.Controls.Add(this.chkIsEnabled);
this.grpEdit.Controls.Add(this.btnSave);
this.grpEdit.Controls.Add(this.btnRefresh);
this.grpEdit.Controls.Add(this.btnNew);
this.grpEdit.Controls.Add(this.btnDelete);
this.grpEdit.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.grpEdit.Location = new System.Drawing.Point(12, 345);
this.grpEdit.Name = "grpEdit";
this.grpEdit.Size = new System.Drawing.Size(760, 165);
this.grpEdit.TabIndex = 1;
this.grpEdit.TabStop = false;
this.grpEdit.Text = "数据新增/编辑(点击表格行可在此查看并编辑该行数据)";
//
// lblEditingHint
//
this.lblEditingHint.AutoSize = true;
this.lblEditingHint.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.lblEditingHint.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(120)))), ((int)(((byte)(215)))));
this.lblEditingHint.Location = new System.Drawing.Point(12, 125);
this.lblEditingHint.Name = "lblEditingHint";
this.lblEditingHint.Size = new System.Drawing.Size(65, 19);
this.lblEditingHint.TabIndex = 0;
this.lblEditingHint.Text = "新增区域";
//
// lblAreaName
//
this.lblAreaName.AutoSize = true;
this.lblAreaName.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lblAreaName.Location = new System.Drawing.Point(12, 28);
this.lblAreaName.Name = "lblAreaName";
this.lblAreaName.Size = new System.Drawing.Size(79, 20);
this.lblAreaName.TabIndex = 1;
this.lblAreaName.Text = "区域名称:";
//
// txtAreaName
//
this.txtAreaName.Font = new System.Drawing.Font("微软雅黑", 10F);
this.txtAreaName.Location = new System.Drawing.Point(100, 24);
this.txtAreaName.Name = "txtAreaName";
this.txtAreaName.Size = new System.Drawing.Size(200, 25);
this.txtAreaName.TabIndex = 2;
//
// lblStationIds
//
this.lblStationIds.AutoSize = true;
this.lblStationIds.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lblStationIds.Location = new System.Drawing.Point(320, 28);
this.lblStationIds.Name = "lblStationIds";
this.lblStationIds.Size = new System.Drawing.Size(79, 20);
this.lblStationIds.TabIndex = 3;
this.lblStationIds.Text = "站点集合:";
//
// txtStationIds
//
this.txtStationIds.Font = new System.Drawing.Font("微软雅黑", 10F);
this.txtStationIds.Location = new System.Drawing.Point(418, 24);
this.txtStationIds.Name = "txtStationIds";
this.txtStationIds.Size = new System.Drawing.Size(320, 25);
this.txtStationIds.TabIndex = 4;
//
// lblControlRight
//
this.lblControlRight.AutoSize = true;
this.lblControlRight.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lblControlRight.Location = new System.Drawing.Point(12, 58);
this.lblControlRight.Name = "lblControlRight";
this.lblControlRight.Size = new System.Drawing.Size(65, 20);
this.lblControlRight.TabIndex = 5;
this.lblControlRight.Text = "控制权:";
//
// txtControlRight
//
this.txtControlRight.Font = new System.Drawing.Font("微软雅黑", 10F);
this.txtControlRight.Location = new System.Drawing.Point(100, 54);
this.txtControlRight.Name = "txtControlRight";
this.txtControlRight.Size = new System.Drawing.Size(200, 25);
this.txtControlRight.TabIndex = 6;
//
// lblIsOccupied
//
this.lblIsOccupied.AutoSize = true;
this.lblIsOccupied.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lblIsOccupied.Location = new System.Drawing.Point(320, 58);
this.lblIsOccupied.Name = "lblIsOccupied";
this.lblIsOccupied.Size = new System.Drawing.Size(93, 20);
this.lblIsOccupied.TabIndex = 7;
this.lblIsOccupied.Text = "是否被占用:";
//
// chkIsOccupied
//
this.chkIsOccupied.AutoSize = true;
this.chkIsOccupied.Font = new System.Drawing.Font("Segoe UI", 9F);
this.chkIsOccupied.Location = new System.Drawing.Point(418, 59);
this.chkIsOccupied.Name = "chkIsOccupied";
this.chkIsOccupied.Size = new System.Drawing.Size(39, 19);
this.chkIsOccupied.TabIndex = 8;
this.chkIsOccupied.Text = "是";
//
// lblIsEnabled
//
this.lblIsEnabled.AutoSize = true;
this.lblIsEnabled.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lblIsEnabled.Location = new System.Drawing.Point(500, 58);
this.lblIsEnabled.Name = "lblIsEnabled";
this.lblIsEnabled.Size = new System.Drawing.Size(79, 20);
this.lblIsEnabled.TabIndex = 9;
this.lblIsEnabled.Text = "是否启用:";
//
// chkIsEnabled
//
this.chkIsEnabled.AutoSize = true;
this.chkIsEnabled.Checked = true;
this.chkIsEnabled.CheckState = System.Windows.Forms.CheckState.Checked;
this.chkIsEnabled.Font = new System.Drawing.Font("Segoe UI", 9F);
this.chkIsEnabled.Location = new System.Drawing.Point(585, 59);
this.chkIsEnabled.Name = "chkIsEnabled";
this.chkIsEnabled.Size = new System.Drawing.Size(39, 19);
this.chkIsEnabled.TabIndex = 10;
this.chkIsEnabled.Text = "是";
//
// btnSave
//
this.btnSave.BackColor = System.Drawing.Color.LightBlue;
this.btnSave.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnSave.Font = new System.Drawing.Font("微软雅黑", 11F, System.Drawing.FontStyle.Bold);
this.btnSave.Location = new System.Drawing.Point(260, 118);
this.btnSave.Name = "btnSave";
this.btnSave.Size = new System.Drawing.Size(140, 40);
this.btnSave.TabIndex = 12;
this.btnSave.Text = "保存";
this.btnSave.UseVisualStyleBackColor = false;
this.btnSave.Click += new System.EventHandler(this.btnSave_Click);
//
// btnRefresh
//
this.btnRefresh.BackColor = System.Drawing.SystemColors.Control;
this.btnRefresh.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnRefresh.Font = new System.Drawing.Font("微软雅黑", 11F);
this.btnRefresh.Location = new System.Drawing.Point(410, 118);
this.btnRefresh.Name = "btnRefresh";
this.btnRefresh.Size = new System.Drawing.Size(140, 40);
this.btnRefresh.TabIndex = 13;
this.btnRefresh.Text = "刷新";
this.btnRefresh.UseVisualStyleBackColor = false;
this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
//
// btnNew
//
this.btnNew.BackColor = System.Drawing.SystemColors.Control;
this.btnNew.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnNew.Font = new System.Drawing.Font("微软雅黑", 11F);
this.btnNew.Location = new System.Drawing.Point(560, 118);
this.btnNew.Name = "btnNew";
this.btnNew.Size = new System.Drawing.Size(140, 40);
this.btnNew.TabIndex = 14;
this.btnNew.Text = "新增";
this.btnNew.UseVisualStyleBackColor = false;
this.btnNew.Click += new System.EventHandler(this.btnNew_Click);
//
// btnDelete
//
this.btnDelete.BackColor = System.Drawing.SystemColors.Control;
this.btnDelete.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnDelete.Font = new System.Drawing.Font("微软雅黑", 11F);
this.btnDelete.Location = new System.Drawing.Point(110, 118);
this.btnDelete.Name = "btnDelete";
this.btnDelete.Size = new System.Drawing.Size(140, 40);
this.btnDelete.TabIndex = 11;
this.btnDelete.Text = "删除";
this.btnDelete.UseVisualStyleBackColor = false;
this.btnDelete.Click += new System.EventHandler(this.btnDelete_Click);
//
// TrafficInterlockViewer
//
this.ClientSize = new System.Drawing.Size(784, 521);
this.Controls.Add(this.lstTasks);
this.Controls.Add(this.grpEdit);
this.Font = new System.Drawing.Font("微软雅黑", 9F);
this.MinimumSize = new System.Drawing.Size(700, 450);
this.Name = "TrafficInterlockViewer";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "交通联锁区域管理";
this.grpEdit.ResumeLayout(false);
this.grpEdit.PerformLayout();
this.ResumeLayout(false);
}
}
}
@@ -1,235 +1,336 @@
using Newtonsoft.Json;
using StandardScene.InterLock; // 数据类型采用 TrafficInterlockMission 中的 TrafficArea
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using System.Threading.Tasks;
using CycleGUI;
using Newtonsoft.Json;
using StandardScene.InterLock;
using StandardScene.Utils;
namespace LoopViewerApp
{
public partial class TrafficInterlockViewer : Form
/// <summary>
/// 交通联锁区域管理界面(CycleGUI 版,替代原 WinForms <c>TrafficInterlockViewer</c> 窗体)。
/// <list type="bullet">
/// <item>维护 <see cref="TrafficInterlockMission.TrafficAreaList"/> 的增 / 改 / 删,并写入 <c>Config/traffic.json</c>。</item>
/// <item>单实例:再次打开则把已有面板置前。</item>
/// <item>勾选多行后「删除选中」可批量删除;每行「编辑」按钮加载下方编辑区。</item>
/// <item>文件写入放后台线程,绝不阻塞渲染线程。</item>
/// </list>
/// 沿用 <c>LoopViewer</c> / <c>DeliveryViewer</c> 同套模式(单实例面板、<c>pb.Table</c>、<c>CycleUiHelper.ConfirmThen</c>)。
/// 保留可实例化 + <see cref="Show"/> 以兼容既有调用 <c>new TrafficInterlockViewer().Show()</c>。
/// </summary>
public class TrafficInterlockViewer
{
/// <summary>-1 表示新增模式;>=0 表示正在编辑对应索引</summary>
private int _editingIndex = -1;
private const string TableId = "traffic-area-list";
/// <summary>选中行变化时是否允许加载到编辑区(避免在保存/取消时重复刷新)</summary>
private bool _allowLoadFromSelection = true;
private static string JsonPath =>
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config", "traffic.json");
public TrafficInterlockViewer()
private static readonly object SaveLock = new object();
private static Panel _panel;
private static string _editingAreaId = "";
private static readonly HashSet<string> _selected = new HashSet<string>(StringComparer.Ordinal);
private static string _areaName = "";
private static string _stationIds = "";
private static string _controlRight = "";
private static bool _isOccupied;
private static bool _isEnabled = true;
private static string _editingHint = "新增区域";
private static string _editErr = "";
private static volatile string _status = "";
/// <summary>打开(或置前)区域管理面板。兼容原 <c>new TrafficInterlockViewer().Show()</c> 调用方式。</summary>
public void Show() => Open();
/// <summary>打开(或置前)区域管理面板。</summary>
public static void Open()
{
InitializeComponent();
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
return;
try
if (_panel != null)
{
RenderListView();
ClearPanelInputs();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"TrafficInterlockViewer init error: {ex}");
}
}
#region
private void lstTasks_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
try
{
// 与 LoopViewer 一致:深蓝表头 + 白色加粗字体
using (var backBrush = new SolidBrush(Color.FromArgb(63, 81, 181)))
using (var textBrush = new SolidBrush(Color.White))
using (var font = new Font("微软雅黑", 9, FontStyle.Bold))
try
{
e.Graphics.FillRectangle(backBrush, e.Bounds);
var sf = new StringFormat { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Near };
var rect = e.Bounds;
rect.Inflate(-8, 0);
e.Graphics.DrawString(e.Header.Text, font, textBrush, rect, sf);
using (var pen = new Pen(Color.FromArgb(200, 200, 200)))
e.Graphics.DrawLine(pen, e.Bounds.Left, e.Bounds.Bottom - 1, e.Bounds.Right, e.Bounds.Bottom - 1);
_panel.BringToFront();
return;
}
catch
{
_panel = null;
}
}
catch
ClearPanelInputs();
var panel = GUI.DeclarePanel()
.ShowTitle("交通联锁区域管理")
.SetDefaultDocking(Panel.Docking.None)
.InitSize(800, 680)
.InitPos(false, 0, 0, 0.5f, 0.5f, 0.5f, 0.5f);
_panel = panel;
panel.IfTerminalQuit(() => { if (_panel == panel) _panel = null; });
panel.Define(pb =>
{
e.DrawBackground();
e.DrawText();
}
if (pb.Closing())
{
panel.Exit();
_panel = null;
return;
}
List<TrafficArea> areas;
lock (TrafficInterlockMission.TrafficAreaList)
{
EnsureAreaIdsLocked();
areas = TrafficInterlockMission.TrafficAreaList.ToList();
}
_selected.RemoveWhere(id => areas.All(a => a.Id != id));
if (!string.IsNullOrEmpty(_editingAreaId) && areas.All(a => a.Id != _editingAreaId))
ClearPanelInputs();
if (pb.Button("删除选中", distinct: "traffic-del-selected"))
ConfirmDeleteSelected();
pb.SameLine(12);
if (pb.Button("刷新", distinct: "traffic-refresh"))
{
_status = "";
_editErr = "";
}
pb.SameLine(12);
pb.Label($"共 {areas.Count} 个区域,已选 {_selected.Count} 个");
pb.Table(TableId,
new[] { "选择", "区域名称", "区域站点集合", "控制权", "是否被占用", "是否启用", "操作" },
areas.Count, (row, i) =>
{
var a = areas[i];
var areaId = EnsureAreaId(a);
var sel = _selected.Contains(areaId);
if (row.Checkbox(ref sel, "勾选以批量删除"))
{
if (sel) _selected.Add(areaId);
else _selected.Remove(areaId);
}
row.Label(a.AreaName ?? "");
row.Label(a.SiteList != null && a.SiteList.Count > 0
? string.Join(", ", a.SiteList)
: "");
row.Label(a.ControllerName ?? "");
row.Label(a.IsOccupy ? "是" : "否");
row.Label(a.IsEnable ? "是" : "否");
if (row.ButtonGroup(new[] { "编辑" }, new[] { "编辑该区域" }) == 0)
{
_editingAreaId = areaId;
LoadAreaToFields(a);
}
}, height: 14, enableSearch: true);
pb.Separator();
pb.Label("数据新增/编辑(点击表格行「编辑」可在此查看并修改该行数据)");
pb.Label(_editingHint);
var (name, _) = pb.TextInput("1. 区域名称", _areaName, alwaysReturnString: true);
_areaName = name;
var (sites, _) = pb.TextInput("2. 站点集合 (逗号/分号/空格分隔)", _stationIds, alwaysReturnString: true);
_stationIds = sites;
var (ctrl, _) = pb.TextInput("3. 控制权", _controlRight, alwaysReturnString: true);
_controlRight = ctrl;
pb.CheckBox("4. 是否被占用", ref _isOccupied);
pb.SameLine(16);
pb.CheckBox("5. 是否启用", ref _isEnabled);
if (!string.IsNullOrEmpty(_editErr))
{
pb.Separator();
pb.Label(_editErr);
}
pb.Separator();
if (pb.Button("保存", distinct: "traffic-save"))
SaveArea();
pb.SameLine(12);
if (pb.Button("新增", distinct: "traffic-new"))
{
_selected.Clear();
ClearPanelInputs();
}
if (!string.IsNullOrEmpty(_status))
{
pb.Separator();
pb.Label(_status);
}
pb.Panel.Repaint(repaintTimeMs: 500);
});
}
private void lstTasks_DrawItem(object sender, DrawListViewItemEventArgs e)
private static void ConfirmDeleteSelected()
{
// 由 DrawSubItem 统一绘制
if (_selected.Count == 0)
{
_status = "请先在上方列表中选择要删除的区域。";
_panel?.Repaint();
return;
}
string prompt = _selected.Count == 1
? "确定要删除选中的区域吗?"
: $"确定要删除所选 {_selected.Count} 个区域吗?";
CycleUiHelper.ConfirmThen(prompt, DeleteSelected);
}
private void lstTasks_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
private static void DeleteSelected()
{
var selectedIds = _selected.ToHashSet(StringComparer.Ordinal);
var removed = 0;
lock (TrafficInterlockMission.TrafficAreaList)
{
removed = TrafficInterlockMission.TrafficAreaList.RemoveAll(a => selectedIds.Contains(a.Id));
}
_selected.Clear();
SaveToConfig();
ClearPanelInputs();
_status = $"已删除 {removed} 个区域";
_panel?.Repaint();
}
private static void SaveArea()
{
try
{
bool selected = e.Item.Selected;
Rectangle bounds = e.Bounds;
// 与 LoopViewer 一致:选中行蓝色强调,交替行背景,深灰文字
Color selectedBack = Color.FromArgb(0, 120, 215);
Color selectedFore = Color.White;
Color evenBack = Color.White;
Color oddBack = Color.FromArgb(250, 251, 253);
Color normalFore = Color.FromArgb(33, 33, 33);
if (selected)
string areaName = (_areaName ?? "").Trim();
if (string.IsNullOrEmpty(areaName))
{
using (var selBrush = new SolidBrush(selectedBack))
e.Graphics.FillRectangle(selBrush, bounds);
_editErr = "请输入区域名称。";
_panel?.Repaint();
return;
}
var stationIds = ParseStationIds(_stationIds ?? "");
string controlRight = (_controlRight ?? "").Trim();
bool isOccupied = _isOccupied;
bool isEnabled = _isEnabled;
if (!string.IsNullOrEmpty(_editingAreaId))
{
lock (TrafficInterlockMission.TrafficAreaList)
{
var existing = TrafficInterlockMission.TrafficAreaList
.FirstOrDefault(a => string.Equals(a.Id, _editingAreaId, StringComparison.Ordinal));
if (existing == null)
{
_editErr = "正在编辑的区域已不存在,请刷新后重试。";
_panel?.Repaint();
return;
}
existing.AreaName = areaName;
existing.SiteList = stationIds;
existing.ControllerName = controlRight;
existing.IsOccupy = isOccupied;
existing.IsEnable = isEnabled;
}
_status = $"已保存区域:{areaName}";
}
else
{
using (var back = new SolidBrush(e.ItemIndex % 2 == 0 ? evenBack : oddBack))
e.Graphics.FillRectangle(back, bounds);
}
string text = e.SubItem?.Text ?? string.Empty;
Color fore = selected ? selectedFore : normalFore;
var textRect = bounds;
textRect.Inflate(-6, 0);
using (var font = new Font("微软雅黑", 9))
TextRenderer.DrawText(e.Graphics, text, font, textRect, fore, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
}
catch
{
e.DrawBackground();
e.DrawText();
}
}
#endregion
#region
private void RenderListView()
{
try
{
if (lstTasks == null) return;
_allowLoadFromSelection = false;
lstTasks.BeginUpdate();
lstTasks.Items.Clear();
foreach (var a in TrafficInterlockMission.TrafficAreaList)
{
var stationStr = a.SiteList != null && a.SiteList.Count > 0 ? string.Join(", ", a.SiteList) : "";
var lvi = new ListViewItem(new[]
lock (TrafficInterlockMission.TrafficAreaList)
{
a.AreaName ?? "",
stationStr,
a.ControllerName ?? "",
a.IsOccupy ? "是" : "否",
a.IsEnable ? "是" : "否"
});
lstTasks.Items.Add(lvi);
TrafficInterlockMission.TrafficAreaList.Add(new TrafficArea
{
Id = NewAreaId(),
AreaName = areaName,
SiteList = stationIds,
ControllerName = controlRight,
IsOccupy = isOccupied,
IsEnable = isEnabled
});
}
_status = "已新增区域";
}
lstTasks.EndUpdate();
_allowLoadFromSelection = true;
SaveToConfig();
ClearPanelInputs();
_editErr = "";
_panel?.Repaint();
}
catch (Exception ex)
{
_allowLoadFromSelection = true;
System.Diagnostics.Debug.WriteLine($"RenderListView failed: {ex}");
_editErr = "操作失败:" + ex.Message;
_panel?.Repaint();
}
}
private void SaveToConfig()
{
try
{
string configPath = Path.Combine(Application.StartupPath, "Config", "traffic.json");
string dir = Path.GetDirectoryName(configPath);
if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
Directory.CreateDirectory(dir);
File.WriteAllText(configPath, JsonConvert.SerializeObject(TrafficInterlockMission.TrafficAreaList, Formatting.Indented));
}
catch (Exception ex)
{
MessageBox.Show("保存失败:" + ex.Message);
}
}
#endregion
#region
private void lstTasks_SelectedIndexChanged(object sender, EventArgs e)
{
if (!_allowLoadFromSelection || lstTasks == null || lstTasks.SelectedIndices.Count == 0) return;
int idx = lstTasks.SelectedIndices[0];
if (idx < 0 || idx >= TrafficInterlockMission.TrafficAreaList.Count) return;
_editingIndex = idx;
LoadAreaToPanel(TrafficInterlockMission.TrafficAreaList[idx]);
}
#endregion
#region /
private void LoadAreaToPanel(TrafficArea a)
private static void LoadAreaToFields(TrafficArea a)
{
if (a == null) return;
try
{
if (lblEditingHint != null)
lblEditingHint.Text = $"编辑:{a.AreaName}";
if (txtAreaName != null)
txtAreaName.Text = a.AreaName ?? "";
if (txtStationIds != null)
txtStationIds.Text = a.SiteList != null && a.SiteList.Count > 0
? string.Join(", ", a.SiteList)
: "";
if (txtControlRight != null)
txtControlRight.Text = a.ControllerName ?? "";
if (chkIsOccupied != null)
chkIsOccupied.Checked = a.IsOccupy;
if (chkIsEnabled != null)
chkIsEnabled.Checked = a.IsEnable;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"LoadAreaToPanel error: {ex}");
}
_editingHint = $"编辑:{a.AreaName}";
_areaName = a.AreaName ?? "";
_stationIds = a.SiteList != null && a.SiteList.Count > 0
? string.Join(", ", a.SiteList)
: "";
_controlRight = a.ControllerName ?? "";
_isOccupied = a.IsOccupy;
_isEnabled = a.IsEnable;
_editErr = "";
}
private void ClearPanelInputs()
private static void ClearPanelInputs()
{
_editingAreaId = "";
_editingHint = "新增区域";
_areaName = "";
_stationIds = "";
_controlRight = "";
_isOccupied = false;
_isEnabled = true;
_editErr = "";
}
private static void SaveToConfig()
{
string json;
try
{
_editingIndex = -1;
if (lblEditingHint != null)
lblEditingHint.Text = "新增区域";
if (txtAreaName != null)
txtAreaName.Text = "";
if (txtStationIds != null)
txtStationIds.Text = "";
if (txtControlRight != null)
txtControlRight.Text = "";
if (chkIsOccupied != null)
chkIsOccupied.Checked = false;
if (chkIsEnabled != null)
chkIsEnabled.Checked = true;
lock (TrafficInterlockMission.TrafficAreaList)
json = JsonConvert.SerializeObject(TrafficInterlockMission.TrafficAreaList, Formatting.Indented);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"ClearPanelInputs error: {ex}");
_status = "保存失败:" + ex.Message;
_panel?.Repaint();
return;
}
var path = JsonPath;
var dir = Path.GetDirectoryName(path);
Task.Run(() =>
{
try
{
if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
Directory.CreateDirectory(dir);
lock (SaveLock)
File.WriteAllText(path, json);
}
catch (Exception ex)
{
_status = "保存失败:" + ex.Message;
_panel?.Repaint();
}
});
}
#endregion
#region "1,2,3" -> List<int>
/// <summary>解析站点集合字符串,如 "1,2,3" → <see cref="List{T}"/> of int。</summary>
private static List<int> ParseStationIds(string text)
{
var list = new List<int>();
@@ -242,129 +343,19 @@ namespace LoopViewerApp
return list;
}
#endregion
#region / / /
private void btnSave_Click(object sender, EventArgs e)
private static void EnsureAreaIdsLocked()
{
try
{
string areaName = txtAreaName?.Text?.Trim() ?? "";
if (string.IsNullOrEmpty(areaName))
{
MessageBox.Show("请输入区域名称。");
return;
}
var stationIds = ParseStationIds(txtStationIds?.Text ?? "");
string controlRight = txtControlRight?.Text?.Trim() ?? "";
bool isOccupied = chkIsOccupied?.Checked ?? false;
bool isEnabled = chkIsEnabled?.Checked ?? true;
if (_editingIndex >= 0 && _editingIndex < TrafficInterlockMission.TrafficAreaList.Count)
{
lock (TrafficInterlockMission.TrafficAreaList)
{
var existing = TrafficInterlockMission.TrafficAreaList[_editingIndex];
existing.AreaName = areaName;
existing.SiteList = stationIds;
existing.ControllerName = controlRight;
existing.IsOccupy = isOccupied;
existing.IsEnable = isEnabled;
}
}
else
{
lock (TrafficInterlockMission.TrafficAreaList)
{
TrafficInterlockMission.TrafficAreaList.Add(new TrafficArea
{
AreaName = areaName,
SiteList = stationIds,
ControllerName = controlRight,
IsOccupy = isOccupied,
IsEnable = isEnabled
});
}
}
SaveToConfig();
RenderListView();
ClearPanelInputs();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"btnSave_Click error: {ex}");
MessageBox.Show("操作失败:" + ex.Message);
}
foreach (var area in TrafficInterlockMission.TrafficAreaList)
EnsureAreaId(area);
}
private void btnRefresh_Click(object sender, EventArgs e)
private static string EnsureAreaId(TrafficArea area)
{
try
{
RenderListView();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"btnRefresh_Click error: {ex}");
}
if (string.IsNullOrWhiteSpace(area.Id))
area.Id = NewAreaId();
return area.Id;
}
private void btnNew_Click(object sender, EventArgs e)
{
if (lstTasks != null)
lstTasks.SelectedIndices.Clear();
ClearPanelInputs();
// 进入新增模式:填写下方编辑区后点击“保存”即可新增一条数据
}
private void btnDelete_Click(object sender, EventArgs e)
{
try
{
if (lstTasks == null || lstTasks.SelectedIndices.Count == 0)
{
MessageBox.Show("请先在上方列表中选择要删除的区域。");
return;
}
var dialogResult = MessageBox.Show(
"确定要删除选中的区域吗?",
"确认删除",
MessageBoxButtons.YesNo,
MessageBoxIcon.Warning);
if (dialogResult != DialogResult.Yes)
return;
var indices = lstTasks.SelectedIndices.Cast<int>()
.OrderByDescending(i => i)
.ToList();
lock (TrafficInterlockMission.TrafficAreaList)
{
foreach (var idx in indices)
{
if (idx >= 0 && idx < TrafficInterlockMission.TrafficAreaList.Count)
{
TrafficInterlockMission.TrafficAreaList.RemoveAt(idx);
}
}
}
SaveToConfig();
RenderListView();
ClearPanelInputs();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"btnDelete_Click error: {ex}");
MessageBox.Show("删除失败:" + ex.Message);
}
}
#endregion
private static string NewAreaId() => Guid.NewGuid().ToString("N");
}
}
@@ -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
View File
@@ -13,7 +13,6 @@ using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json;
using SimpleLite.RCS;
using SimpleLite.RCS.CarTypes;
@@ -6,3 +6,5 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("StandardScene.Devices")]
[assembly: InternalsVisibleTo("StandardScene.Magnetic")]
[assembly: InternalsVisibleTo("StandardScene.QrLidar")]
// SimpleLite 反射 API 需读取 internal 字段袋(BasicTrackFields / KivaSiteFields 等)的 public 字段定义。
[assembly: InternalsVisibleTo("SimpleLite")]
+3 -292
View File
@@ -1,294 +1,5 @@
using Newtonsoft.Json;
using SimpleLite;
using SimpleLite.RCS;
using SimpleLite.RCS.CarTypes;
using SimpleLite.CADTools;
using SimpleLite.Props;
using SimpleLite.UI;
using SimpleCore;
using SimpleCore.Library;
using SimpleCore.PropType;
using StandardScene.Model;
using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace StandardScene
namespace StandardScene
{
[CADToolDescriptor(name = "复制目标站点所有字段")]
public class CopySiteFieldsFromTarget : CADTool
{
public override async void Invoke()
{
var sel = SimpleMonitor.selected.OfType<UISite>().ToList();
var targetPoint = await Program.UI.getPoint(new UIOps.getPointOptions() { site = true });
var targetSite = SimpleLib.GetSite(targetPoint.site);
var ignoreKey = new string[] { "mustFree" };
if (sel.Count <= 0) return;
foreach (var site in sel)
{
foreach (var field in targetSite.fields)
{
if (ignoreKey.Contains(field.Key)) continue;
site.fields[field.Key] = field.Value;
}
}
}
}
[CADToolDescriptor(name = "区域流量管控-限制进入区域的车数量")]
public class RegionalTrafficControl : CADTool
{
// 重写调用方法:执行区域流量管控的车辆数量限制配置
public override async void Invoke()
{
// 获取选中的所有站点UI对象
var selectedSites = SimpleMonitor.selected.OfType<UISite>().ToList();
// 弹出输入框,提示用户按「区域编号,限制数量」格式输入,取消则直接返回
var inputDialogResult = InputBox.ShowDialog("请输入区域编号和限制数量,格式:1,3");
if (inputDialogResult != SimpleLite.DialogResult.OK) return;
// 拆分输入的区域编号和限制数量
var inputValues = InputBox.ResultValue.Split(',');
// 若无配置信息,直接返回
if (inputValues.Length <= 1) return;
// 解析区域编号(浮点型保留原类型,兼容后续扩展)
var areaNumber = float.Parse(inputValues[0]);
// 解析区域车辆限制数量(浮点型保留原类型,兼容非整数配置)
var limitVehicleCount = float.Parse(inputValues[1]);
// 遍历所有选中站点,为其添加区域流量管控的字段配置
foreach (var currentSite in selectedSites)
{
// 配置字段:area+区域编号 作为键,限制数量作为值
if (!currentSite.fields.ContainsKey($"Region{areaNumber}"))
{
currentSite.fields.Add($"Region{areaNumber}", limitVehicleCount.ToString());
}
}
}
}
[CADToolDescriptor(name = "复制目标站点所有字段(不覆盖)")]
public class CopySiteFieldsFromTargetNoOverwrite : CADTool
{
public override async void Invoke()
{
var sel = SimpleMonitor.selected.OfType<UISite>().ToList();
var targetPoint = await Program.UI.getPoint(new UIOps.getPointOptions() { site = true });
var targetSite = SimpleLib.GetSite(targetPoint.site);
var ignore = new string[] { "mustFree" };
if (sel.Count <= 0) return;
foreach (var site in sel)
{
foreach (var field in targetSite.fields)
{
if (!site.fields.ContainsKey(field.Key))
{
site.fields[field.Key] = field.Value;
}
}
}
}
}
[CADToolDescriptor(name = "复制目标站点颜色")]
public class BatchChangeSiteColor : CADTool
{
public override async void Invoke()
{
var sel = SimpleMonitor.selected.OfType<UISite>().ToList();
var targetPoint = await Program.UI.getPoint(new UIOps.getPointOptions() { site = true });
var targetSite = (UISite)SimpleLib.GetSite(targetPoint.site);
if (sel.Count <= 0) return;
foreach (var site in sel)
{
site.color = targetSite.color;
}
}
}
[CADToolDescriptor(name = "导入FASS地图")]
public class ImportFASSMap : CADTool
{
public override void Invoke()
{
//打开文件选择框
using (var ofd = new System.Windows.Forms.OpenFileDialog())
{
ofd.InitialDirectory = "C:\\";
ofd.Filter = "FASS地图文件(*.json)|*.json";
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string filePath = ofd.FileName;
//解析文件内容
string jsonString = File.ReadAllText(filePath);
MapStructure mapStructure = JsonConvert.DeserializeObject<MapStructure>(jsonString);
Model.Configuration configuration = ConvertMapStructureToConfiguration(mapStructure);
// 输出 JSON 字符串到文本文件
// 将 MapStructure 对象序列化为 JSON 字符串
// 设置格式化选项
string jsonSsring = JsonConvert.SerializeObject(configuration);
// 获取桌面路径
string desktopPath =
AppDomain.CurrentDomain
.BaseDirectory; // Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string outPath = Path.Combine(desktopPath, "output.json"); // 输出文件路径
// 输出 JSON 字符串到桌面上的文本文件
File.WriteAllText(outPath, jsonSsring);
Console.WriteLine($"JSON 数据已成功写入到 {outPath}");
//todo:分析文件内容,并导入站点、路径信息
}
}
}
public static Model.Configuration ConvertMapStructureToConfiguration(MapStructure mapStructure)
{
Model.Configuration config = new Model.Configuration();
List<int> index = new List<int>();
// 处理 Sites
foreach (var node in mapStructure.Nodes)
{
SimpleSite site = new SimpleSite
{
id = int.Parse(node.Code.Text), // 将 node.Code.Text 赋值给 SimpleSite 的 Id
name = node.Name.Text, // 将 node.Name.Text 赋值给 SimpleSite 的 Name
x = node.Base.Point.X, // 将 node.Base.Point.X 赋值给 SimpleSite 的 X
y = node.Base.Point.Y, // 将 node.Base.Point.Y 赋值给 SimpleSite 的 Y
color = "defaultColor", // 默认颜色示例,您可以根据需要更改
displaySetting = "defaultDisplay", // 默认显示设置示例,您可以根据需要更改
fields = new Dictionary<string, string>(), // Assuming fields is an empty object
mustFree = new List<object>() // Assuming mustFree is an empty array
};
config.Sites[node.Code.Text] = site; // 将 SimpleSite 添加到 Sites 字典中
AddInDescendingOrder(index, int.Parse(node.Code.Text));
}
// 处理 Tracks
foreach (var edge in mapStructure.Edges)
{
int id = index[0] + 1;
AddInDescendingOrder(index, id);
StandardScene.Model.Track track = new StandardScene.Model.Track
{
id = id, // 将 edge.Index 赋值给 Track 的 Id
name = "NoName", // 将 edge.Name.Text 赋值给 Track 的 Name
siteA = int.Parse(mapStructure.Nodes.Find(n => n.Id == edge.Data.StartNodeId).Code
.Text), // 找到 StartNode 的索引
siteB = int.Parse(mapStructure.Nodes.Find(n => n.Id == edge.Data.EndNodeId).Code
.Text), // 找到 EndNode 的索引
_siteA = int.Parse(mapStructure.Nodes.Find(n => n.Id == edge.Data.StartNodeId).Code.Text),
_siteB = int.Parse(mapStructure.Nodes.Find(n => n.Id == edge.Data.EndNodeId).Code.Text),
fields = new Dictionary<string, string>(),
typeInfo = "0",
layerName = "g",
displaySetting = ""
};
config.Tracks[id.ToString()] = track; // 将 Track 添加到 Tracks 字典中
}
return config;
}
static void AddInDescendingOrder(List<int> list, int number)
{
// 找到插入位置
int i = 0;
while (i < list.Count && list[i] >= number)
{
i++;
}
list.Insert(i, number); // 在找到的位置插入
}
}
[CADToolDescriptor(name = "批量间距生成站点")]
public class BulkIntervalSiteCreator : CADTool
{
public override async void Invoke()
{
try
{
G.pushStatus("请选择参考点");
var target = await Program.UI.getPoint();
var templateSite = SimpleLib.GetAllSites().OrderBy(p => LessMath.dist(target.x, target.y, p.x, p.y))
.FirstOrDefault();
// 检查是否找到模板站点
if (templateSite == null)
{
G.pushStatus("未找到参考站点");
return;
}
// 存储所有生成的站点(用于处理组间连接)
List<UISite> generatedSites = new List<UISite>();
if (InputBox.ShowDialog("请输入需要生成的二维码数量(必须是偶数数量)以及站点间距和延伸角度,,格式为\"6,1000,0\"。") !=
SimpleLite.DialogResult.OK) return;
generatedSites.Add((UISite)templateSite);
var values = InputBox.ResultValue.Split(',').Select(ss => float.Parse(ss)).ToArray();
// 验证数量是否为偶数
if (values[0] % 2 != 0)
{
G.pushStatus("数量必须是偶数");
return;
}
for (int i = 0; i < values[0] / 2; i = i + 2)
{
var curPos = Tuple.Create(templateSite.x, templateSite.y, values[2]);
var targetPos = LessMath.Transform2D(curPos, Tuple.Create(values[1] * (i + 1), 0f, 0f));
var targetPos2 = LessMath.Transform2D(curPos, Tuple.Create(values[1] * (i + 2), 0f, 0f));
var siteA = new UISite() { id = Prop.GenerateID(), x = targetPos.Item1, y = targetPos.Item2 };
((UISite)siteA).color = ""; //
var siteB = new UISite() { id = Prop.GenerateID(), x = targetPos2.Item1, y = targetPos2.Item2 };
SimpleLib.SetSite(siteA);
SimpleLib.SetSite(siteB);
generatedSites.Add(siteA);
generatedSites.Add(siteB);
}
for (int i = 0; i < generatedSites.Count - 1; i++)
{
Commons.AddOrUpdateSiteField(generatedSites[i], "tag", "0");
// 每两个相邻站点都创建路径(包含组内和组间)
SimpleLib.SetTrack(new UITrack(
generatedSites[i].id,
generatedSites[i + 1].id
));
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
// SyncQrMap(同步二维码地图到小车)已迁出至 StandardScene.QrLidar\Cad\SyncQrMap.csscene.qrlidar 平台)。
// StandardScene 的 CAD 工具已迁移到 SimpleLite.CADTools.StandardSceneTools。
// 保留此文件作为迁移记录,避免后续误以为遗漏了 StandardScene 侧工具。
}
+7 -1
View File
@@ -3,7 +3,6 @@
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<OutputType>Library</OutputType>
<UseWindowsForms>true</UseWindowsForms>
<RootNamespace>StandardScene</RootNamespace>
<AssemblyName>StandardScene</AssemblyName>
<LangVersion>latest</LangVersion>
@@ -29,6 +28,12 @@
<Reference Include="SimpleLite">
<HintPath>E:\Work\Core\Simple-FR\Simple\SimpleLite\bin\Debug\SimpleLite.dll</HintPath>
</Reference>
<!-- CycleGUI:插件 UI 已从 WinForms 迁移到 CycleGUIDeliveryViewer 等)。
Private=false:宿主 SimpleLite 已在默认 ALC 加载 CycleGUI,插件仅编译期引用、不随产物分发,避免重复 DLL。 -->
<Reference Include="CycleGUI">
<HintPath>$(CGUILibDir)\CycleGUI.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="SimpleCore">
<HintPath>E:\Work\Core\Simple-FR\Simple\SimpleCore\bin\Debug\netstandard2.0\SimpleCore.dll</HintPath>
</Reference>
@@ -59,6 +64,7 @@
<PackageReference Include="MQTTnet.Extensions.ManagedClient" Version="4.3.6.1152" />
<PackageReference Include="Nancy" Version="2.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="System.Drawing.Common" Version="9.0.0" />
</ItemGroup>
</Project>
-1
View File
@@ -7,7 +7,6 @@ using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolTip;
namespace StandardScene.TCP
{
@@ -0,0 +1,37 @@
using System;
using System.Diagnostics;
namespace StandardScene.Utils
{
/// <summary>
/// 车辆远程访问辅助工具。
/// </summary>
public static class CarRemoteHelper
{
/// <summary>
/// 使用系统默认浏览器打开车辆 Web 管理页面。
/// </summary>
/// <param name="ip">车辆 IP 地址</param>
/// <param name="port">Web 服务端口,默认 8081</param>
public static void OpenVehicleWebPage(string ip, int port = 8081)
{
if (string.IsNullOrWhiteSpace(ip))
{
return;
}
try
{
Process.Start(new ProcessStartInfo
{
FileName = $"http://{ip}:{port}",
UseShellExecute = true
});
}
catch (Exception ex)
{
Console.WriteLine($"打开车辆 Web 页面失败: {ex.Message}");
}
}
}
}
+91
View File
@@ -0,0 +1,91 @@
using CycleGUI;
namespace StandardScene.Utils
{
/// <summary>
/// CycleGUI 通用 UI 小工具:把多个界面都会用到的轻量对话框收敛到一处,避免各处各写一套(不造重复轮子)。
/// <para>注意:同一 <c>Panel.Define</c> 内所有控件的 label 文本必须唯一(含 <c>pb.Table</c> 列头),
/// 否则 ImGui 会抛 <c>Duplicated id</c>。编辑区 label 建议加 ASCII 序号前缀(如 <c>1. IP</c>),
/// 且勿与表格列头同名。</para>
/// </summary>
public static class CycleUiHelper
{
/// <summary>
/// 非阻塞二次确认对话框:用户点「确认」后,在<b>当前(渲染)线程</b>同步执行 <paramref name="onConfirm"/>。
/// 若 <paramref name="onConfirm"/> 含文件 IO / 锁等耗时操作,调用方应自行用 <c>Task.Run</c> 包裹,
/// 避免阻塞渲染线程导致界面卡死。
/// </summary>
public static void ConfirmThen(string message, System.Action onConfirm)
{
// 不用 ModalCycleGUI 原生「模态弹窗 + 标题栏关闭X」存在 BeginPopupModal/EndPopup 配对 bug
//X 关闭时 BeginPopupModal 返回 false 仍调用 EndPopup → ImGui 断言 "Calling End() too many times!" 崩溃)。
// 改为置顶非模态:用 Begin/End 路径,X 关闭干净,效果等同点「取消」。
var dlg = GUI.DeclarePanel()
.ShowTitle("确认")
.TopMost(true)
.InitSize(380, 150)
.InitPos(false, 0, 0, 0.5f, 0.5f, 0.5f, 0.5f);
dlg.Define(pb =>
{
if (pb.Closing())
{
dlg.Exit();
return;
}
pb.Label(message);
pb.Separator();
if (pb.Button("确认", distinct: "cycleui-confirm-ok"))
{
dlg.Exit();
onConfirm();
}
pb.SameLine(8);
if (pb.Button("取消", distinct: "cycleui-confirm-cancel"))
dlg.Exit();
});
}
/// <summary>非阻塞文件选择对话框,替代 WinForms <c>OpenFileDialog</c>。</summary>
public static void PickOpenFile(string label, string filter, System.Action<string> onPicked)
{
var dlg = GUI.DeclarePanel()
.ShowTitle("选择文件")
.TopMost(true)
.InitSize(420, 120)
.InitPos(false, 0, 0, 0.5f, 0.5f, 0.5f, 0.5f);
dlg.Define(pb =>
{
if (pb.Closing()) { dlg.Exit(); return; }
if (pb.OpenFile(label, filter, out var path))
{
dlg.Exit();
onPicked?.Invoke(path);
}
});
}
/// <summary>非阻塞提示对话框。</summary>
public static void Alert(string title, string message)
{
var dlg = GUI.DeclarePanel()
.ShowTitle(title)
.TopMost(true)
.InitSize(380, 150)
.InitPos(false, 0, 0, 0.5f, 0.5f, 0.5f, 0.5f);
dlg.Define(pb =>
{
if (pb.Closing())
{
dlg.Exit();
return;
}
pb.Label(message);
pb.Separator();
if (pb.Button("确定", distinct: "cycleui-alert-ok"))
dlg.Exit();
});
}
}
}