refactor: 插件 UI 从 WinForms 迁移到 CycleGUI,并修复代码质量问题
将 StandardScene 各插件的配置/监控窗体从 WinForms 迁移到 CycleGUI(删除 .Designer.cs/.resx,重写为 PanelBuilder 立即模式 UI,新增 CycleUiHelper 统一对话框)。 同时修复代码审核中的问题: - 后台文件写入加锁 + try/catch(ButtonBoxManager / DoorManager,对齐 LoopViewer.SaveTasks 模式) - CoderFieldsMetadata.cs 启用 #nullable enable,消除 CS8632 警告 - DummyCar 移除已废弃的 rightClickAction()/SetPosition() - CarRemoteHelper.OpenVehicleWebPage 的 Process.Start 加 try/catch - 重命名名不副实的 Mstsc()(现为打开网页) - 统一弃元命名为 _ - TrafficInterlockViewer 改用稳定 Id(GUID)做选择/编辑,替代行索引 - csproj 改用 $(CGUILibDir) 解析 CycleGUI,绝对路径收敛到 Directory.Build.props 构建:dotnet build StandardScene.sln → 0 错误,30 警告(均为历史遗留)。 注:static 单例状态重构(审核第 8 项)暂未处理,留待单独任务。
This commit is contained in:
@@ -1,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.cs(scene.qrlidar 平台)。
|
||||
// StandardScene 的 CAD 工具已迁移到 SimpleLite.CADTools.StandardSceneTools。
|
||||
// 保留此文件作为迁移记录,避免后续误以为遗漏了 StandardScene 侧工具。
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user