refactor: CycleUiHelper 重命名为 FairyUiHelper

对齐 FairyView 宿主命名。环线/充电/按钮/门进程的 Stop 改为 override,避免隐藏基类;Kiva.ForceStop 改为 override。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
黄兆尉
2026-08-26 22:49:07 +08:00
co-authored by Cursor
parent 7c925985eb
commit e075bc0d7d
23 changed files with 143 additions and 116 deletions
+1 -1
View File
@@ -240,7 +240,7 @@ public sealed class MagneticSceneProfile : NavigationProfileBase
| `Coders/` | 导航无关的通用轨迹编码器 | `CommonTrackCoders`, `LidarAreaSwitchCoder` | | `Coders/` | 导航无关的通用轨迹编码器 | `CommonTrackCoders`, `LidarAreaSwitchCoder` |
| `Model/` | 任务、地图、配置数据模型 | `TaskModel`, `LoopTask`, `Map`, `ChargingSetting` | | `Model/` | 任务、地图、配置数据模型 | `TaskModel`, `LoopTask`, `Map`, `ChargingSetting` |
| `TCP/` | 异步 TCP 客户端 | `AsyncTcpClient` | | `TCP/` | 异步 TCP 客户端 | `AsyncTcpClient` |
| `Utils/` | JSON、Modbus、WebAPI、CycleGUI 辅助 | `WebAPIHelper`, `CycleUiHelper`, `CarRemoteHelper` | | `Utils/` | JSON、Modbus、WebAPI、FairyView UI 辅助 | `WebAPIHelper`, `FairyUiHelper`, `CarRemoteHelper` |
| `CommonTools/` | 原子文件写入、雪花 ID | `AtomicFileUpdateHelper`, `SnowflakeIdGenerator` | | `CommonTools/` | 原子文件写入、雪花 ID | `AtomicFileUpdateHelper`, `SnowflakeIdGenerator` |
| 根目录 | 全局工具与 HTTP 入口 | `Commons.cs`, `WebApi.cs`, `Heuristic.cs`, `LadderLogic.cs` | | 根目录 | 全局工具与 HTTP 入口 | `Commons.cs`, `WebApi.cs`, `Heuristic.cs`, `LadderLogic.cs` |
+2 -2
View File
@@ -509,7 +509,7 @@ namespace AMRScene1
{ {
Task.Run(() => Task.Run(() =>
{ {
CycleUiHelper.Alert("提示", "go?"); FairyUiHelper.Alert("提示", "go?");
go(); go();
}); });
}); });
@@ -599,7 +599,7 @@ namespace AMRScene1
string tag = InputBox.ResultValue; string tag = InputBox.ResultValue;
if (tag.Contains("")) if (tag.Contains(""))
{ {
CycleUiHelper.Alert("提示", "需要切换英文输入法输入:"); FairyUiHelper.Alert("提示", "需要切换英文输入法输入:");
return; return;
} }
if (!string.IsNullOrEmpty(tag) && tag.Contains(":")) if (!string.IsNullOrEmpty(tag) && tag.Contains(":"))
@@ -2172,7 +2172,7 @@ namespace StandardScene.Chained
} }
[MethodMember(Name = "停止环线", Description = "停止环线")] [MethodMember(Name = "停止环线", Description = "停止环线")]
public void Stop() public override void Stop()
{ {
StopAll(); StopAll();
} }
@@ -2182,7 +2182,7 @@ namespace StandardScene.Chained
ConfirmMessage = "确认将所有已初始化的正常 AGV 一键上线?")] ConfirmMessage = "确认将所有已初始化的正常 AGV 一键上线?")]
public void OnlineAllCars() public void OnlineAllCars()
{ {
// 确认由 MethodMember.ConfirmMessage + ObjectEditorParity/SafeUI 居中弹出,此处勿再套 CycleUiHelper。 // 确认由 MethodMember.ConfirmMessage + ObjectEditorParity/SafeUI 居中弹出,此处勿再套 FairyUiHelper。
Task.Run(OnlineAllCarsCore); Task.Run(OnlineAllCarsCore);
} }
@@ -2208,7 +2208,7 @@ namespace StandardScene.Chained
ConfirmMessage = "确认停止环线调度并结束所有 AGV 的环线任务?")] ConfirmMessage = "确认停止环线调度并结束所有 AGV 的环线任务?")]
public void StopAllCarTasks() public void StopAllCarTasks()
{ {
// 确认由 MethodMember.ConfirmMessage + ObjectEditorParity/SafeUI 居中弹出,此处勿再套 CycleUiHelper。 // 确认由 MethodMember.ConfirmMessage + ObjectEditorParity/SafeUI 居中弹出,此处勿再套 FairyUiHelper。
Task.Run(StopAllCarTasksCore); Task.Run(StopAllCarTasksCore);
} }
+4 -4
View File
@@ -137,10 +137,10 @@ namespace StandardScene.Chained
new[] { "取消任务", "重发任务", "换车重发任务" }); new[] { "取消任务", "重发任务", "换车重发任务" });
var taskCode = dd.Id; var taskCode = dd.Id;
// 业务操作含文件 IO 与锁竞争,统一用 Task.Run 放后台执行,绝不阻塞渲染线程(否则界面卡死)。 // 业务操作含文件 IO 与锁竞争,统一用 Task.Run 放后台执行,绝不阻塞渲染线程(否则界面卡死)。
if (op == 0) CycleUiHelper.ConfirmThen($"是否结束任务 {taskCode}", () => Task.Run(() => CancelDelivery(taskCode))); if (op == 0) FairyUiHelper.ConfirmThen($"是否结束任务 {taskCode}", () => Task.Run(() => CancelDelivery(taskCode)));
else if (op == 1) CycleUiHelper.ConfirmThen($"是否重发任务 {taskCode}", () => Task.Run(() => ResendDelivery(taskCode))); else if (op == 1) FairyUiHelper.ConfirmThen($"是否重发任务 {taskCode}", () => Task.Run(() => ResendDelivery(taskCode)));
else if (op == 2) CycleUiHelper.ConfirmThen($"是否换车重发任务 {taskCode}", () => Task.Run(() => ChangeCarResendDelivery(taskCode))); else if (op == 2) FairyUiHelper.ConfirmThen($"是否换车重发任务 {taskCode}", () => Task.Run(() => ChangeCarResendDelivery(taskCode)));
}, height: CycleUiHelper.TableHeightPx(18), enableSearch: true); }, height: FairyUiHelper.TableHeightPx(18), enableSearch: true);
if (!string.IsNullOrEmpty(_status)) if (!string.IsNullOrEmpty(_status))
{ {
+3 -3
View File
@@ -19,7 +19,7 @@ namespace LoopViewerApp
/// <item>勾选多行后「删除选中」可批量删除(保留原 ListView 多选删除能力);每行「编辑」按钮打开编辑对话框。</item> /// <item>勾选多行后「删除选中」可批量删除(保留原 ListView 多选删除能力);每行「编辑」按钮打开编辑对话框。</item>
/// <item>文件写入放后台线程,绝不阻塞渲染线程(避免界面卡死)。</item> /// <item>文件写入放后台线程,绝不阻塞渲染线程(避免界面卡死)。</item>
/// </list> /// </list>
/// 沿用 <c>DeliveryViewer</c> 的同套模式(单实例面板、<c>pb.Table</c>、<c>CycleUiHelper.ConfirmThen</c>),不另造轮子。 /// 沿用 <c>DeliveryViewer</c> 的同套模式(单实例面板、<c>pb.Table</c>、<c>FairyUiHelper.ConfirmThen</c>),不另造轮子。
/// 保留可实例化 + <see cref="Show"/> 以兼容既有调用 <c>new LoopViewer().Show()</c>。 /// 保留可实例化 + <see cref="Show"/> 以兼容既有调用 <c>new LoopViewer().Show()</c>。
/// </summary> /// </summary>
public class LoopViewer public class LoopViewer
@@ -116,7 +116,7 @@ namespace LoopViewerApp
if (row.ButtonGroup(new[] { "编辑" }, new[] { "编辑该任务" }) == 0) if (row.ButtonGroup(new[] { "编辑" }, new[] { "编辑该任务" }) == 0)
OpenEditDialog(t); OpenEditDialog(t);
}, height: CycleUiHelper.TableHeightPx(18), enableSearch: true); }, height: FairyUiHelper.TableHeightPx(18), enableSearch: true);
if (!string.IsNullOrEmpty(_status)) if (!string.IsNullOrEmpty(_status))
{ {
@@ -146,7 +146,7 @@ namespace LoopViewerApp
prompt = $"确认删除所选 {_selected.Count} 个任务?"; prompt = $"确认删除所选 {_selected.Count} 个任务?";
// 删除仅做内存列表增删(极快,可在渲染线程执行);真正的文件写入在 SaveTasks 内部放后台线程。 // 删除仅做内存列表增删(极快,可在渲染线程执行);真正的文件写入在 SaveTasks 内部放后台线程。
CycleUiHelper.ConfirmThen(prompt, DeleteSelected); FairyUiHelper.ConfirmThen(prompt, DeleteSelected);
} }
private void DeleteSelected() private void DeleteSelected()
@@ -373,7 +373,7 @@ namespace StandardScene.Chained
{ {
if (_simRunning) if (_simRunning)
{ {
CycleUiHelper.Alert("提示", "模拟下发搬运任务已在运行中。"); FairyUiHelper.Alert("提示", "模拟下发搬运任务已在运行中。");
return; return;
} }
@@ -461,7 +461,7 @@ namespace StandardScene.Chained
{ {
G.pushStatus("选择小车"); G.pushStatus("选择小车");
var selected = SimpleMonitor.selected.ToArray(); var selected = SimpleMonitor.selected.ToArray();
if (selected.Length == 0) { CycleUiHelper.Alert("提示", "请先选择需要控制的小车!"); return; } if (selected.Length == 0) { FairyUiHelper.Alert("提示", "请先选择需要控制的小车!"); return; }
var obj = selected[0]; var obj = selected[0];
if (obj is Car car) if (obj is Car car)
{ {
@@ -485,7 +485,7 @@ namespace StandardScene.Chained
} }
else else
{ {
CycleUiHelper.Alert("提示", "请选择需要控制的小车!"); FairyUiHelper.Alert("提示", "请选择需要控制的小车!");
} }
} }
catch catch
@@ -512,7 +512,7 @@ namespace StandardScene.Chained
{ {
G.pushStatus("选择小车"); G.pushStatus("选择小车");
var selected = SimpleMonitor.selected.ToArray(); var selected = SimpleMonitor.selected.ToArray();
if (selected.Length == 0) { CycleUiHelper.Alert("提示", "请先选择需要控制的小车!"); return; } if (selected.Length == 0) { FairyUiHelper.Alert("提示", "请先选择需要控制的小车!"); return; }
var obj = selected[0]; var obj = selected[0];
if (obj is Car car) if (obj is Car car)
{ {
@@ -537,7 +537,7 @@ namespace StandardScene.Chained
} }
else else
{ {
CycleUiHelper.Alert("提示", "请选择需要控制的小车!"); FairyUiHelper.Alert("提示", "请选择需要控制的小车!");
} }
} }
catch catch
@@ -124,7 +124,7 @@ namespace StandardScene.Charge
if (row.ButtonGroup(new[] { "编辑" }, new[] { "编辑该报警配置" }) == 0) if (row.ButtonGroup(new[] { "编辑" }, new[] { "编辑该报警配置" }) == 0)
OpenEditDialog(alarm); OpenEditDialog(alarm);
}, height: CycleUiHelper.TableHeightPx(16), enableSearch: true); }, height: FairyUiHelper.TableHeightPx(16), enableSearch: true);
if (!string.IsNullOrEmpty(_status)) if (!string.IsNullOrEmpty(_status))
{ {
@@ -231,7 +231,7 @@ namespace StandardScene.Charge
if (success) if (success)
{ {
CycleUiHelper.Alert("成功", "保存成功!"); FairyUiHelper.Alert("成功", "保存成功!");
LoadAlarms(); LoadAlarms();
_status = isAdd ? "已新增报警配置" : $"已保存报警配置 [{draft.AlarmCode}]"; _status = isAdd ? "已新增报警配置" : $"已保存报警配置 [{draft.AlarmCode}]";
dlg.Exit(); dlg.Exit();
@@ -250,13 +250,13 @@ namespace StandardScene.Charge
if (pb.Button("删除", distinct: "alarm-edit-delete")) if (pb.Button("删除", distinct: "alarm-edit-delete"))
{ {
var toDelete = draft; var toDelete = draft;
CycleUiHelper.ConfirmThen( FairyUiHelper.ConfirmThen(
$"确定要删除报警配置 [{toDelete.AlarmCode}] {toDelete.AlarmContent} 吗?", $"确定要删除报警配置 [{toDelete.AlarmCode}] {toDelete.AlarmContent} 吗?",
() => () =>
{ {
if (DataService.DeleteAlarmConfig(toDelete.AlarmId, out string errorMessage)) if (DataService.DeleteAlarmConfig(toDelete.AlarmId, out string errorMessage))
{ {
CycleUiHelper.Alert("成功", "删除成功!"); FairyUiHelper.Alert("成功", "删除成功!");
LoadAlarms(); LoadAlarms();
_status = $"已删除报警配置 [{toDelete.AlarmCode}]"; _status = $"已删除报警配置 [{toDelete.AlarmCode}]";
dlg.Exit(); dlg.Exit();
@@ -265,7 +265,7 @@ namespace StandardScene.Charge
} }
else else
{ {
CycleUiHelper.Alert("错误", $"删除失败: {errorMessage}"); FairyUiHelper.Alert("错误", $"删除失败: {errorMessage}");
} }
}); });
} }
@@ -289,7 +289,7 @@ namespace StandardScene.Charge
catch (Exception ex) catch (Exception ex)
{ {
_allAlarms = new List<AlarmConfig>(); _allAlarms = new List<AlarmConfig>();
CycleUiHelper.Alert("错误", $"加载数据失败: {ex.Message}"); FairyUiHelper.Alert("错误", $"加载数据失败: {ex.Message}");
} }
} }
@@ -282,7 +282,7 @@ namespace StandardScene.Charge
if (stations.Count == 0) if (stations.Count == 0)
{ {
CycleUiHelper.Alert("提示", "没有符合条件的充电桩"); FairyUiHelper.Alert("提示", "没有符合条件的充电桩");
onSelected?.Invoke(null); onSelected?.Invoke(null);
return; return;
} }
@@ -129,7 +129,7 @@ namespace StandardScene.Charge
var op = row.ButtonGroup(new[] { "编辑", "删除" }, new[] { "编辑充电桩", "删除充电桩" }); var op = row.ButtonGroup(new[] { "编辑", "删除" }, new[] { "编辑充电桩", "删除充电桩" });
if (op == 0) OpenEditDialog(s); if (op == 0) OpenEditDialog(s);
else if (op == 1) ConfirmDelete(s); else if (op == 1) ConfirmDelete(s);
}, height: CycleUiHelper.TableHeightPx(16), enableSearch: true); }, height: FairyUiHelper.TableHeightPx(16), enableSearch: true);
if (!string.IsNullOrEmpty(_status)) if (!string.IsNullOrEmpty(_status))
{ {
@@ -290,7 +290,7 @@ namespace StandardScene.Charge
_lastFlush = DateTime.MinValue; _lastFlush = DateTime.MinValue;
_status = "保存成功"; _status = "保存成功";
CycleUiHelper.Alert("提示", "保存成功"); FairyUiHelper.Alert("提示", "保存成功");
dlg.Exit(); dlg.Exit();
_editDialog = null; _editDialog = null;
_panel?.Repaint(); _panel?.Repaint();
@@ -341,11 +341,11 @@ namespace StandardScene.Charge
private void ConfirmDelete(ChargeStation station) private void ConfirmDelete(ChargeStation station)
{ {
CycleUiHelper.ConfirmThen($"确定删除充电桩 [{station.StationId}] {station.Name}", () => FairyUiHelper.ConfirmThen($"确定删除充电桩 [{station.StationId}] {station.Name}", () =>
{ {
if (!DataService.DeleteStation(station.StationId, out var err)) if (!DataService.DeleteStation(station.StationId, out var err))
{ {
CycleUiHelper.Alert("错误", $"删除失败: {err}"); FairyUiHelper.Alert("错误", $"删除失败: {err}");
return; return;
} }
var site = SimpleLib.GetSite(station.SiteId ?? 0); var site = SimpleLib.GetSite(station.SiteId ?? 0);
@@ -384,9 +384,9 @@ namespace StandardScene.Charge
{ {
File.WriteAllText(path, Newtonsoft.Json.JsonConvert.SerializeObject(stations, Newtonsoft.Json.Formatting.Indented)); File.WriteAllText(path, Newtonsoft.Json.JsonConvert.SerializeObject(stations, Newtonsoft.Json.Formatting.Indented));
} }
CycleUiHelper.Alert("提示", "导出成功"); FairyUiHelper.Alert("提示", "导出成功");
} }
catch (Exception ex) { CycleUiHelper.Alert("错误", $"导出失败: {ex.Message}"); } catch (Exception ex) { FairyUiHelper.Alert("错误", $"导出失败: {ex.Message}"); }
} }
private void ApplyRowColor(PanelBuilder.Row row, ChargeStation s) private void ApplyRowColor(PanelBuilder.Row row, ChargeStation s)
@@ -135,7 +135,7 @@ namespace StandardScene.Charge
} }
catch (Exception ex) catch (Exception ex)
{ {
CycleUiHelper.Alert("错误", $"加载配置失败: {ex.Message}"); FairyUiHelper.Alert("错误", $"加载配置失败: {ex.Message}");
_status = "配置加载失败"; _status = "配置加载失败";
return false; return false;
} }
@@ -220,7 +220,7 @@ namespace StandardScene.Charge
if (!ValidateSocRanges(out var socError)) if (!ValidateSocRanges(out var socError))
{ {
CycleUiHelper.Alert("验证失败", socError); FairyUiHelper.Alert("验证失败", socError);
_status = "配置保存失败"; _status = "配置保存失败";
_panel?.Repaint(); _panel?.Repaint();
return; return;
@@ -230,7 +230,7 @@ namespace StandardScene.Charge
{ {
ConfigService.SaveConfig(_config); ConfigService.SaveConfig(_config);
_status = "配置保存成功"; _status = "配置保存成功";
CycleUiHelper.Alert("成功", "充电策略配置保存成功!"); FairyUiHelper.Alert("成功", "充电策略配置保存成功!");
if (closeAfterSave) if (closeAfterSave)
{ {
_panel?.Exit(); _panel?.Exit();
@@ -243,7 +243,7 @@ namespace StandardScene.Charge
} }
catch (Exception ex) catch (Exception ex)
{ {
CycleUiHelper.Alert("错误", $"保存配置失败: {ex.Message}"); FairyUiHelper.Alert("错误", $"保存配置失败: {ex.Message}");
_status = "配置保存失败"; _status = "配置保存失败";
_panel?.Repaint(); _panel?.Repaint();
} }
@@ -251,7 +251,7 @@ namespace StandardScene.Charge
private void RestoreDefaults() private void RestoreDefaults()
{ {
CycleUiHelper.ConfirmThen("确定要恢复默认配置吗?当前配置将被覆盖。", () => FairyUiHelper.ConfirmThen("确定要恢复默认配置吗?当前配置将被覆盖。", () =>
{ {
_config = ChargeStrategyConfig.CreateDefault(); _config = ChargeStrategyConfig.CreateDefault();
ApplyConfigToUi(_config); ApplyConfigToUi(_config);
@@ -117,7 +117,7 @@ namespace StandardScene.Charge
pb.SameLine(8); pb.SameLine(8);
if (pb.Button("清空", distinct: "comm-clear")) if (pb.Button("清空", distinct: "comm-clear"))
{ {
CycleUiHelper.ConfirmThen("确定要清空所有报文记录吗?", () => FairyUiHelper.ConfirmThen("确定要清空所有报文记录吗?", () =>
{ {
MessageService.Clear(); MessageService.Clear();
lock (PendingLock) lock (PendingLock)
@@ -164,7 +164,7 @@ namespace StandardScene.Charge
_selectedRowIndex = i; _selectedRowIndex = i;
_parsedText = BuildParsedText(msg); _parsedText = BuildParsedText(msg);
} }
}, height: CycleUiHelper.TableHeightPx(20), enableSearch: true); }, height: FairyUiHelper.TableHeightPx(20), enableSearch: true);
pb.SeparatorText("报文解析"); pb.SeparatorText("报文解析");
pb.SelectableText(null, _parsedText ?? "", copyButton: true); pb.SelectableText(null, _parsedText ?? "", copyButton: true);
@@ -278,7 +278,7 @@ namespace StandardScene.Charge
// 防止重复启动 // 防止重复启动
if (myStarted) if (myStarted)
{ {
CycleUiHelper.Alert("提示", "充电进程已启动,不可重复启动"); FairyUiHelper.Alert("提示", "充电进程已启动,不可重复启动");
return; return;
} }
status.status = "已启动"; status.status = "已启动";
@@ -671,7 +671,7 @@ namespace StandardScene.Charge
/// 停止所有相关线程 /// 停止所有相关线程
/// </summary> /// </summary>
[MethodMember(Name = "关闭进程", Description = "关闭充电进程")] [MethodMember(Name = "关闭进程", Description = "关闭充电进程")]
public void Stop() public override void Stop()
{ {
try try
{ {
+1 -1
View File
@@ -39,7 +39,7 @@ namespace StandardScene
var cars = string.Join(",", loopingCar.Select(p => $"{p.id}")); var cars = string.Join(",", loopingCar.Select(p => $"{p.id}"));
var msg = $"小车:{cars}间发生死锁" + var msg = $"小车:{cars}间发生死锁" +
$"请及时人工介入处理!!!!"; $"请及时人工介入处理!!!!";
CycleUiHelper.Alert("死锁提醒", msg); FairyUiHelper.Alert("死锁提醒", msg);
} }
catch { } catch { }
}; };
@@ -95,7 +95,7 @@ namespace StandardScene.ExtendDevice.ButtonBox
LoadBoxFields(b); LoadBoxFields(b);
ClearButtonFields(); ClearButtonFields();
} }
}, height: CycleUiHelper.TableHeightPx(8), enableSearch: true); }, height: FairyUiHelper.TableHeightPx(8), enableSearch: true);
pb.SeparatorText("按钮盒编辑"); pb.SeparatorText("按钮盒编辑");
var (ip, _) = pb.TextInput("1. IP", _boxIp, alwaysReturnString: true); var (ip, _) = pb.TextInput("1. IP", _boxIp, alwaysReturnString: true);
@@ -130,7 +130,7 @@ namespace StandardScene.ExtendDevice.ButtonBox
_selectedBtnIdx = i; _selectedBtnIdx = i;
LoadButtonFields(btn); LoadButtonFields(btn);
} }
}, height: CycleUiHelper.TableHeightPx(6), enableSearch: true); }, height: FairyUiHelper.TableHeightPx(6), enableSearch: true);
pb.SeparatorText("按钮编辑"); pb.SeparatorText("按钮编辑");
var (bIdx, _) = pb.TextInput("5. 按钮编码", _btnIndex, alwaysReturnString: true); var (bIdx, _) = pb.TextInput("5. 按钮编码", _btnIndex, alwaysReturnString: true);
@@ -264,9 +264,9 @@ namespace StandardScene.ExtendDevice.ButtonBox
private void AddBox() private void AddBox()
{ {
if (!TryParseBoxInput(out var index, out var ip, out var port, out var type, false, out var err)) if (!TryParseBoxInput(out var index, out var ip, out var port, out var type, false, out var err))
{ CycleUiHelper.Alert("错误", err); return; } { FairyUiHelper.Alert("错误", err); return; }
if (_boxes.Any(b => b.Index == index)) { CycleUiHelper.Alert("错误", $"编码 {index} 已存在"); return; } if (_boxes.Any(b => b.Index == index)) { FairyUiHelper.Alert("错误", $"编码 {index} 已存在"); return; }
if (_boxes.Any(b => b.Ip == ip)) { CycleUiHelper.Alert("错误", $"IP {ip} 已存在"); return; } if (_boxes.Any(b => b.Ip == ip)) { FairyUiHelper.Alert("错误", $"IP {ip} 已存在"); return; }
var box = new ButtonBoxModel { Index = index, Ip = ip, Port = port, Type = type }; var box = new ButtonBoxModel { Index = index, Ip = ip, Port = port, Type = type };
_boxes.Add(box); _boxes.Add(box);
@@ -279,23 +279,23 @@ namespace StandardScene.ExtendDevice.ButtonBox
private void SaveBox() private void SaveBox()
{ {
var cur = GetSelectedBox(); var cur = GetSelectedBox();
if (cur == null) { CycleUiHelper.Alert("提示", "请先选择按钮盒"); return; } if (cur == null) { FairyUiHelper.Alert("提示", "请先选择按钮盒"); return; }
if (!TryParseBoxInput(out var index, out var ip, out var port, out var type, true, out var err)) if (!TryParseBoxInput(out var index, out var ip, out var port, out var type, true, out var err))
{ CycleUiHelper.Alert("错误", err); return; } { FairyUiHelper.Alert("错误", err); return; }
if (_boxes.Any(b => b.Index == index && b != cur)) { CycleUiHelper.Alert("错误", $"编码 {index} 已存在"); return; } if (_boxes.Any(b => b.Index == index && b != cur)) { FairyUiHelper.Alert("错误", $"编码 {index} 已存在"); return; }
if (_boxes.Any(b => b.Ip == ip && b != cur)) { CycleUiHelper.Alert("错误", $"IP {ip} 已存在"); return; } if (_boxes.Any(b => b.Ip == ip && b != cur)) { FairyUiHelper.Alert("错误", $"IP {ip} 已存在"); return; }
cur.Index = index; cur.Ip = ip; cur.Port = port; cur.Type = type; cur.Index = index; cur.Ip = ip; cur.Port = port; cur.Type = type;
SaveData(); SaveData();
CycleUiHelper.Alert("提示", "保存成功"); FairyUiHelper.Alert("提示", "保存成功");
_panel?.Repaint(); _panel?.Repaint();
} }
private void ConfirmDeleteBox() private void ConfirmDeleteBox()
{ {
var cur = GetSelectedBox(); var cur = GetSelectedBox();
if (cur == null) { CycleUiHelper.Alert("提示", "请选择要删除的按钮盒"); return; } if (cur == null) { FairyUiHelper.Alert("提示", "请选择要删除的按钮盒"); return; }
CycleUiHelper.ConfirmThen($"删除编码为 {cur.Index} 的按钮盒?", () => FairyUiHelper.ConfirmThen($"删除编码为 {cur.Index} 的按钮盒?", () =>
{ {
_boxes.Remove(cur); _boxes.Remove(cur);
_selectedBoxIdx = -1; _selectedBoxIdx = -1;
@@ -311,10 +311,10 @@ namespace StandardScene.ExtendDevice.ButtonBox
private void AddButton() private void AddButton()
{ {
var box = GetSelectedBox(); var box = GetSelectedBox();
if (box == null) { CycleUiHelper.Alert("提示", "请先选择按钮盒"); return; } if (box == null) { FairyUiHelper.Alert("提示", "请先选择按钮盒"); return; }
if (!TryParseButtonInput(out var index, out var delay, out var err)) if (!TryParseButtonInput(out var index, out var delay, out var err))
{ CycleUiHelper.Alert("错误", err); return; } { FairyUiHelper.Alert("错误", err); return; }
if (box.Buttons.Any(b => b.Index == index)) { CycleUiHelper.Alert("错误", $"按钮编码 {index} 已存在"); return; } if (box.Buttons.Any(b => b.Index == index)) { FairyUiHelper.Alert("错误", $"按钮编码 {index} 已存在"); return; }
box.Buttons.Add(new ButtonModel box.Buttons.Add(new ButtonModel
{ {
@@ -335,10 +335,10 @@ namespace StandardScene.ExtendDevice.ButtonBox
{ {
var box = GetSelectedBox(); var box = GetSelectedBox();
var btn = GetSelectedButton(); var btn = GetSelectedButton();
if (box == null || btn == null) { CycleUiHelper.Alert("提示", "请先选择按钮"); return; } if (box == null || btn == null) { FairyUiHelper.Alert("提示", "请先选择按钮"); return; }
if (!TryParseButtonInput(out var index, out var delay, out var err)) if (!TryParseButtonInput(out var index, out var delay, out var err))
{ CycleUiHelper.Alert("错误", err); return; } { FairyUiHelper.Alert("错误", err); return; }
if (box.Buttons.Any(b => b.Index == index && b != btn)) { CycleUiHelper.Alert("错误", $"按钮编码 {index} 已存在"); return; } if (box.Buttons.Any(b => b.Index == index && b != btn)) { FairyUiHelper.Alert("错误", $"按钮编码 {index} 已存在"); return; }
btn.Index = index; btn.Index = index;
btn.TriggerMission = _triggerMission.Trim(); btn.TriggerMission = _triggerMission.Trim();
@@ -347,7 +347,7 @@ namespace StandardScene.ExtendDevice.ButtonBox
btn.TriggerState = _triggerStateNames[_triggerStateIdx]; btn.TriggerState = _triggerStateNames[_triggerStateIdx];
btn.TriggerDelay = delay; btn.TriggerDelay = delay;
SaveData(); SaveData();
CycleUiHelper.Alert("提示", "保存成功"); FairyUiHelper.Alert("提示", "保存成功");
_panel?.Repaint(); _panel?.Repaint();
} }
@@ -355,8 +355,8 @@ namespace StandardScene.ExtendDevice.ButtonBox
{ {
var box = GetSelectedBox(); var box = GetSelectedBox();
var btn = GetSelectedButton(); var btn = GetSelectedButton();
if (box == null || btn == null) { CycleUiHelper.Alert("提示", "请选择要删除的按钮"); return; } if (box == null || btn == null) { FairyUiHelper.Alert("提示", "请选择要删除的按钮"); return; }
CycleUiHelper.ConfirmThen($"删除编码为 {btn.Index} 的按钮?", () => FairyUiHelper.ConfirmThen($"删除编码为 {btn.Index} 的按钮?", () =>
{ {
box.Buttons.Remove(btn); box.Buttons.Remove(btn);
_selectedBtnIdx = -1; _selectedBtnIdx = -1;
@@ -112,7 +112,7 @@ namespace StandardScene.ExtendDevice.ButtonBox
/// </summary> /// </summary>
[MethodMember(Name = "停止进程")] [MethodMember(Name = "停止进程")]
[I18N.DocumentTranslation(Name = "Stop Mission", locale = "en")] [I18N.DocumentTranslation(Name = "Stop Mission", locale = "en")]
public void Stop() public override void Stop()
{ {
StopInternalAsync().GetAwaiter().GetResult(); StopInternalAsync().GetAwaiter().GetResult();
status.status = "/"; status.status = "/";
@@ -768,7 +768,7 @@ namespace StandardScene.ExtendDevice.ButtonBox
public static void OpenViewer() public static void OpenViewer()
{ {
try { ButtonBoxManager.Open(); } try { ButtonBoxManager.Open(); }
catch (Exception ex) { CycleUiHelper.Alert("错误", $"打开按钮盒管理界面失败: {ex.Message}"); } catch (Exception ex) { FairyUiHelper.Alert("错误", $"打开按钮盒管理界面失败: {ex.Message}"); }
} }
} }
} }
@@ -93,7 +93,7 @@ namespace StandardScene.ExtendDevice.Door
LoadControllerFields(c); LoadControllerFields(c);
ClearDoorFields(); ClearDoorFields();
} }
}, height: CycleUiHelper.TableHeightPx(8), enableSearch: true); }, height: FairyUiHelper.TableHeightPx(8), enableSearch: true);
pb.SeparatorText("控制器编辑"); pb.SeparatorText("控制器编辑");
var (ip, _) = pb.TextInput("1. IP", _ctrlIp, alwaysReturnString: true); var (ip, _) = pb.TextInput("1. IP", _ctrlIp, alwaysReturnString: true);
@@ -127,7 +127,7 @@ namespace StandardScene.ExtendDevice.Door
_selectedDoorIdx = i; _selectedDoorIdx = i;
LoadDoorFields(d); LoadDoorFields(d);
} }
}, height: CycleUiHelper.TableHeightPx(6), enableSearch: true); }, height: FairyUiHelper.TableHeightPx(6), enableSearch: true);
pb.SeparatorText("门编辑"); pb.SeparatorText("门编辑");
var (dIdx, _) = pb.TextInput("5. 门编码", _doorIndex, alwaysReturnString: true); var (dIdx, _) = pb.TextInput("5. 门编码", _doorIndex, alwaysReturnString: true);
@@ -256,11 +256,11 @@ namespace StandardScene.ExtendDevice.Door
{ {
if (!TryParseControllerInput(out var index, out var ip, out var port, out var type, false, out var err)) if (!TryParseControllerInput(out var index, out var ip, out var port, out var type, false, out var err))
{ {
CycleUiHelper.Alert("错误", err); FairyUiHelper.Alert("错误", err);
return; return;
} }
if (_controllers.Any(c => c.Index == index)) { CycleUiHelper.Alert("错误", $"编码 {index} 已存在"); return; } if (_controllers.Any(c => c.Index == index)) { FairyUiHelper.Alert("错误", $"编码 {index} 已存在"); return; }
if (_controllers.Any(c => c.Ip == ip)) { CycleUiHelper.Alert("错误", $"IP {ip} 已存在"); return; } if (_controllers.Any(c => c.Ip == ip)) { FairyUiHelper.Alert("错误", $"IP {ip} 已存在"); return; }
var c = new DoorControllerModel { Index = index, Ip = ip, Port = port, Type = type }; var c = new DoorControllerModel { Index = index, Ip = ip, Port = port, Type = type };
_controllers.Add(c); _controllers.Add(c);
@@ -273,14 +273,14 @@ namespace StandardScene.ExtendDevice.Door
private void SaveController() private void SaveController()
{ {
var cur = GetSelectedController(); var cur = GetSelectedController();
if (cur == null) { CycleUiHelper.Alert("提示", "请先选择要保存的门控制器"); return; } if (cur == null) { FairyUiHelper.Alert("提示", "请先选择要保存的门控制器"); return; }
if (!TryParseControllerInput(out var index, out var ip, out var port, out var type, true, out var err)) if (!TryParseControllerInput(out var index, out var ip, out var port, out var type, true, out var err))
{ {
CycleUiHelper.Alert("错误", err); FairyUiHelper.Alert("错误", err);
return; return;
} }
if (_controllers.Any(c => c.Index == index && c != cur)) { CycleUiHelper.Alert("错误", $"编码 {index} 已存在"); return; } if (_controllers.Any(c => c.Index == index && c != cur)) { FairyUiHelper.Alert("错误", $"编码 {index} 已存在"); return; }
if (_controllers.Any(c => c.Ip == ip && c != cur)) { CycleUiHelper.Alert("错误", $"IP {ip} 已存在"); return; } if (_controllers.Any(c => c.Ip == ip && c != cur)) { FairyUiHelper.Alert("错误", $"IP {ip} 已存在"); return; }
cur.Index = index; cur.Index = index;
cur.Ip = ip; cur.Ip = ip;
@@ -288,15 +288,15 @@ namespace StandardScene.ExtendDevice.Door
cur.Type = type; cur.Type = type;
SaveData(); SaveData();
_status = "门控制器已保存"; _status = "门控制器已保存";
CycleUiHelper.Alert("提示", "保存成功"); FairyUiHelper.Alert("提示", "保存成功");
_panel?.Repaint(); _panel?.Repaint();
} }
private void ConfirmDeleteController() private void ConfirmDeleteController()
{ {
var cur = GetSelectedController(); var cur = GetSelectedController();
if (cur == null) { CycleUiHelper.Alert("提示", "请选择要删除的门控制器"); return; } if (cur == null) { FairyUiHelper.Alert("提示", "请选择要删除的门控制器"); return; }
CycleUiHelper.ConfirmThen($"删除编码为 {cur.Index} 的门控制器?", () => FairyUiHelper.ConfirmThen($"删除编码为 {cur.Index} 的门控制器?", () =>
{ {
_controllers.Remove(cur); _controllers.Remove(cur);
_selectedCtrlIdx = -1; _selectedCtrlIdx = -1;
@@ -312,13 +312,13 @@ namespace StandardScene.ExtendDevice.Door
private void AddDoor() private void AddDoor()
{ {
var ctrl = GetSelectedController(); var ctrl = GetSelectedController();
if (ctrl == null) { CycleUiHelper.Alert("提示", "请先选择门控制器"); return; } if (ctrl == null) { FairyUiHelper.Alert("提示", "请先选择门控制器"); return; }
if (!TryParseDoorInput(out var index, out var cAddr, out var oAddr, false, out var err)) if (!TryParseDoorInput(out var index, out var cAddr, out var oAddr, false, out var err))
{ {
CycleUiHelper.Alert("错误", err); FairyUiHelper.Alert("错误", err);
return; return;
} }
if (ctrl.Doors.Any(d => d.Index == index)) { CycleUiHelper.Alert("错误", $"门编码 {index} 已存在"); return; } if (ctrl.Doors.Any(d => d.Index == index)) { FairyUiHelper.Alert("错误", $"门编码 {index} 已存在"); return; }
var door = new DoorModel var door = new DoorModel
{ {
@@ -338,13 +338,13 @@ namespace StandardScene.ExtendDevice.Door
{ {
var ctrl = GetSelectedController(); var ctrl = GetSelectedController();
var door = GetSelectedDoor(); var door = GetSelectedDoor();
if (ctrl == null || door == null) { CycleUiHelper.Alert("提示", "请先选择要保存的门"); return; } if (ctrl == null || door == null) { FairyUiHelper.Alert("提示", "请先选择要保存的门"); return; }
if (!TryParseDoorInput(out var index, out var cAddr, out var oAddr, true, out var err)) if (!TryParseDoorInput(out var index, out var cAddr, out var oAddr, true, out var err))
{ {
CycleUiHelper.Alert("错误", err); FairyUiHelper.Alert("错误", err);
return; return;
} }
if (ctrl.Doors.Any(d => d.Index == index && d != door)) { CycleUiHelper.Alert("错误", $"门编码 {index} 已存在"); return; } if (ctrl.Doors.Any(d => d.Index == index && d != door)) { FairyUiHelper.Alert("错误", $"门编码 {index} 已存在"); return; }
door.Index = index; door.Index = index;
door.ControlAddress = cAddr; door.ControlAddress = cAddr;
@@ -352,7 +352,7 @@ namespace StandardScene.ExtendDevice.Door
door.NoControl = _doorNoControl; door.NoControl = _doorNoControl;
SaveData(); SaveData();
_status = "门已保存"; _status = "门已保存";
CycleUiHelper.Alert("提示", "保存成功"); FairyUiHelper.Alert("提示", "保存成功");
_panel?.Repaint(); _panel?.Repaint();
} }
@@ -360,8 +360,8 @@ namespace StandardScene.ExtendDevice.Door
{ {
var ctrl = GetSelectedController(); var ctrl = GetSelectedController();
var door = GetSelectedDoor(); var door = GetSelectedDoor();
if (ctrl == null || door == null) { CycleUiHelper.Alert("提示", "请选择要删除的门"); return; } if (ctrl == null || door == null) { FairyUiHelper.Alert("提示", "请选择要删除的门"); return; }
CycleUiHelper.ConfirmThen($"删除编码为 {door.Index} 的门?", () => FairyUiHelper.ConfirmThen($"删除编码为 {door.Index} 的门?", () =>
{ {
ctrl.Doors.Remove(door); ctrl.Doors.Remove(door);
_selectedDoorIdx = -1; _selectedDoorIdx = -1;
@@ -141,7 +141,7 @@ namespace StandardScene.ExtendDevice.Door
/// </summary> /// </summary>
[MethodMember(Name = "停止进程")] [MethodMember(Name = "停止进程")]
[I18N.DocumentTranslation(Name = "Stop Mission", locale = "en")] [I18N.DocumentTranslation(Name = "Stop Mission", locale = "en")]
public void Stop() public override void Stop()
{ {
StopInternalAsync().GetAwaiter().GetResult(); StopInternalAsync().GetAwaiter().GetResult();
status.status = "/"; status.status = "/";
@@ -1017,7 +1017,7 @@ namespace StandardScene.ExtendDevice.Door
} }
catch (Exception ex) catch (Exception ex)
{ {
CycleUiHelper.Alert("错误", $"打开门控监控界面失败: {ex.Message}"); FairyUiHelper.Alert("错误", $"打开门控监控界面失败: {ex.Message}");
} }
} }
} }
@@ -90,7 +90,7 @@ namespace StandardScene.ExtendDevice.Door
LabelCell(row, door, FormatCars(door)); LabelCell(row, door, FormatCars(door));
LabelCell(row, door, door.ControlAddress.ToString()); LabelCell(row, door, door.ControlAddress.ToString());
LabelCell(row, door, door.OpenStatusAddress.ToString()); LabelCell(row, door, door.OpenStatusAddress.ToString());
}, height: CycleUiHelper.TableHeightPx(18), enableSearch: true); }, height: FairyUiHelper.TableHeightPx(18), enableSearch: true);
pb.Separator(); pb.Separator();
pb.Label("手动控制"); pb.Label("手动控制");
@@ -161,7 +161,7 @@ namespace StandardScene.ExtendDevice.Door
{ {
if (!_selectedDoor.HasValue) if (!_selectedDoor.HasValue)
{ {
CycleUiHelper.Alert("提示", "请先选择要控制的门"); FairyUiHelper.Alert("提示", "请先选择要控制的门");
return; return;
} }
@@ -170,17 +170,17 @@ namespace StandardScene.ExtendDevice.Door
var mission = GetMission(); var mission = GetMission();
if (mission == null) if (mission == null)
{ {
CycleUiHelper.Alert("错误", "未找到门控进程"); FairyUiHelper.Alert("错误", "未找到门控进程");
return; return;
} }
var (controllerIndex, doorIndex) = _selectedDoor.Value; var (controllerIndex, doorIndex) = _selectedDoor.Value;
mission.SetManualDoorControl(controllerIndex, doorIndex, true); mission.SetManualDoorControl(controllerIndex, doorIndex, true);
CycleUiHelper.Alert("提示", $"控制器 {controllerIndex} 门 {doorIndex} 已设置手动打开(10秒)"); FairyUiHelper.Alert("提示", $"控制器 {controllerIndex} 门 {doorIndex} 已设置手动打开(10秒)");
} }
catch (Exception ex) catch (Exception ex)
{ {
CycleUiHelper.Alert("错误", $"设置门打开目标失败: {ex.Message}"); FairyUiHelper.Alert("错误", $"设置门打开目标失败: {ex.Message}");
} }
} }
@@ -188,7 +188,7 @@ namespace StandardScene.ExtendDevice.Door
{ {
if (!_selectedDoor.HasValue) if (!_selectedDoor.HasValue)
{ {
CycleUiHelper.Alert("提示", "请先选择要控制的门"); FairyUiHelper.Alert("提示", "请先选择要控制的门");
return; return;
} }
@@ -197,7 +197,7 @@ namespace StandardScene.ExtendDevice.Door
var mission = GetMission(); var mission = GetMission();
if (mission == null) if (mission == null)
{ {
CycleUiHelper.Alert("错误", "未找到门控进程"); FairyUiHelper.Alert("错误", "未找到门控进程");
return; return;
} }
@@ -205,15 +205,15 @@ namespace StandardScene.ExtendDevice.Door
var success = mission.SetManualDoorControl(controllerIndex, doorIndex, false); var success = mission.SetManualDoorControl(controllerIndex, doorIndex, false);
if (!success) if (!success)
{ {
CycleUiHelper.Alert("提示", "门存在车辆占用,禁止手动关闭。"); FairyUiHelper.Alert("提示", "门存在车辆占用,禁止手动关闭。");
return; return;
} }
CycleUiHelper.Alert("提示", $"控制器 {controllerIndex} 门 {doorIndex} 已设置手动关闭(10秒)"); FairyUiHelper.Alert("提示", $"控制器 {controllerIndex} 门 {doorIndex} 已设置手动关闭(10秒)");
} }
catch (Exception ex) catch (Exception ex)
{ {
CycleUiHelper.Alert("错误", $"设置门关闭目标失败: {ex.Message}"); FairyUiHelper.Alert("错误", $"设置门关闭目标失败: {ex.Message}");
} }
} }
@@ -221,7 +221,7 @@ namespace StandardScene.ExtendDevice.Door
{ {
if (!_selectedDoor.HasValue) if (!_selectedDoor.HasValue)
{ {
CycleUiHelper.Alert("提示", "请先选择要清空占用的门"); FairyUiHelper.Alert("提示", "请先选择要清空占用的门");
return; return;
} }
@@ -230,17 +230,17 @@ namespace StandardScene.ExtendDevice.Door
var mission = GetMission(); var mission = GetMission();
if (mission == null) if (mission == null)
{ {
CycleUiHelper.Alert("错误", "未找到门控进程"); FairyUiHelper.Alert("错误", "未找到门控进程");
return; return;
} }
var (controllerIndex, doorIndex) = _selectedDoor.Value; var (controllerIndex, doorIndex) = _selectedDoor.Value;
mission.ClearCarsInArea(controllerIndex, doorIndex); mission.ClearCarsInArea(controllerIndex, doorIndex);
CycleUiHelper.Alert("提示", $"控制器 {controllerIndex} 门 {doorIndex} 已清空占用"); FairyUiHelper.Alert("提示", $"控制器 {controllerIndex} 门 {doorIndex} 已清空占用");
} }
catch (Exception ex) catch (Exception ex)
{ {
CycleUiHelper.Alert("错误", $"清空占用失败: {ex.Message}"); FairyUiHelper.Alert("错误", $"清空占用失败: {ex.Message}");
} }
} }
} }
@@ -297,7 +297,7 @@ namespace StandardScene.InterLock
var vv = await Startup.UI.Input("请输入true/false", title, "true"); var vv = await Startup.UI.Input("请输入true/false", title, "true");
if (vv == null || !bool.TryParse(vv, out var allow)) if (vv == null || !bool.TryParse(vv, out var allow))
{ {
CycleUiHelper.Alert("错误", "输入错误"); FairyUiHelper.Alert("错误", "输入错误");
return; return;
} }
lock (sync) toManipulate[site.id] = allow; lock (sync) toManipulate[site.id] = allow;
@@ -18,7 +18,7 @@ namespace LoopViewerApp
/// <item>勾选多行后「删除选中」可批量删除;每行「编辑」按钮加载下方编辑区。</item> /// <item>勾选多行后「删除选中」可批量删除;每行「编辑」按钮加载下方编辑区。</item>
/// <item>文件写入放后台线程,绝不阻塞渲染线程。</item> /// <item>文件写入放后台线程,绝不阻塞渲染线程。</item>
/// </list> /// </list>
/// 沿用 <c>LoopViewer</c> / <c>DeliveryViewer</c> 同套模式(单实例面板、<c>pb.Table</c>、<c>CycleUiHelper.ConfirmThen</c>)。 /// 沿用 <c>LoopViewer</c> / <c>DeliveryViewer</c> 同套模式(单实例面板、<c>pb.Table</c>、<c>FairyUiHelper.ConfirmThen</c>)。
/// 保留可实例化 + <see cref="Show"/> 以兼容既有调用 <c>new TrafficInterlockViewer().Show()</c>。 /// 保留可实例化 + <see cref="Show"/> 以兼容既有调用 <c>new TrafficInterlockViewer().Show()</c>。
/// </summary> /// </summary>
public class TrafficInterlockViewer public class TrafficInterlockViewer
@@ -133,7 +133,7 @@ namespace LoopViewerApp
_editingAreaId = areaId; _editingAreaId = areaId;
LoadAreaToFields(a); LoadAreaToFields(a);
} }
}, height: CycleUiHelper.TableHeightPx(14), enableSearch: true); }, height: FairyUiHelper.TableHeightPx(14), enableSearch: true);
pb.Separator(); pb.Separator();
pb.Label("数据新增/编辑(点击表格行「编辑」可在此查看并修改该行数据)"); pb.Label("数据新增/编辑(点击表格行「编辑」可在此查看并修改该行数据)");
@@ -188,7 +188,7 @@ namespace LoopViewerApp
? "确定要删除选中的区域吗?" ? "确定要删除选中的区域吗?"
: $"确定要删除所选 {_selected.Count} 个区域吗?"; : $"确定要删除所选 {_selected.Count} 个区域吗?";
CycleUiHelper.ConfirmThen(prompt, DeleteSelected); FairyUiHelper.ConfirmThen(prompt, DeleteSelected);
} }
private void DeleteSelected() private void DeleteSelected()
@@ -1,24 +1,44 @@
using FairyView; using FairyView;
using Simple3;
namespace StandardScene.Utils namespace StandardScene.Utils
{ {
/// <summary> /// <summary>
/// CycleGUI 通用 UI 小工具:统一委托 SafeUI 居中弹窗,避免自建 Panel 缺 Docking.None 跑到左上角 /// FairyView 通用 UI 小工具:浮动居中弹窗,不依赖宿主 SafeUI
/// </summary> /// </summary>
public static class CycleUiHelper public static class FairyUiHelper
{ {
/// <summary> /// <summary>
/// 非阻塞二次确认:用户点「确认」后在当前线程执行 <paramref name="onConfirm"/>。 /// 非阻塞二次确认:用户点「确认」后在当前线程执行 <paramref name="onConfirm"/>。
/// 耗时逻辑请自行 <c>Task.Run</c>。 /// 耗时逻辑请自行 <c>Task.Run</c>。
/// </summary> /// </summary>
public static void ConfirmThen(string message, System.Action onConfirm) => public static void ConfirmThen(string message, System.Action onConfirm)
SafeUI.ConfirmThen(message, onConfirm); {
var dlg = CenteredDialog(GUI.DeclarePanel().ShowTitle("确认"), 380, 150);
dlg.Define(pb =>
{
if (pb.Closing())
{
dlg.Exit();
return;
}
pb.Label(message);
pb.Separator();
if (pb.Button("确认", distinct: "fairyui-confirm-ok"))
{
dlg.Exit();
onConfirm?.Invoke();
}
pb.SameLine(8);
if (pb.Button("取消", distinct: "fairyui-confirm-cancel"))
dlg.Exit();
});
}
/// <summary>非阻塞文件选择对话框。</summary> /// <summary>非阻塞文件选择对话框。</summary>
public static void PickOpenFile(string label, string filter, System.Action<string> onPicked) public static void PickOpenFile(string label, string filter, System.Action<string> onPicked)
{ {
var dlg = SafeUI.ApplyCenteredFloating(GUI.DeclarePanel().ShowTitle("选择文件"), 420, 120); var dlg = CenteredDialog(GUI.DeclarePanel().ShowTitle("选择文件"), 420, 120);
dlg.Define(pb => dlg.Define(pb =>
{ {
if (pb.Closing()) if (pb.Closing())
@@ -38,7 +58,7 @@ namespace StandardScene.Utils
/// <summary>非阻塞提示对话框。</summary> /// <summary>非阻塞提示对话框。</summary>
public static void Alert(string title, string message) public static void Alert(string title, string message)
{ {
var dlg = SafeUI.ApplyCenteredFloating(GUI.DeclarePanel().ShowTitle(title), 380, 150); var dlg = CenteredDialog(GUI.DeclarePanel().ShowTitle(title), 380, 150);
dlg.Define(pb => dlg.Define(pb =>
{ {
if (pb.Closing()) if (pb.Closing())
@@ -49,7 +69,7 @@ namespace StandardScene.Utils
pb.Label(message); pb.Label(message);
pb.Separator(); pb.Separator();
if (pb.Button("确定", distinct: "cycleui-alert-ok")) if (pb.Button("确定", distinct: "fairyui-alert-ok"))
dlg.Exit(); dlg.Exit();
}); });
} }
@@ -59,5 +79,12 @@ namespace StandardScene.Utils
/// </summary> /// </summary>
public static int TableHeightPx(int visibleRows) => public static int TableHeightPx(int visibleRows) =>
visibleRows <= 0 ? 0 : visibleRows * 32; visibleRows <= 0 ? 0 : visibleRows * 32;
static Panel CenteredDialog(Panel panel, int width, int height) =>
panel
.TopMost(true)
.ForceFloat()
.InitSize(width, height)
.InitPos(true, 0, 0, 0.5f, 0.5f, 0.5f, 0.5f);
} }
} }
+1 -1
View File
@@ -30,7 +30,7 @@ namespace StandardScene.QrLidar.Cad
var tagTh = tagSite.fields.TryGetValue("th", out var field) ? float.Parse(field) : 0f; var tagTh = tagSite.fields.TryGetValue("th", out var field) ? float.Parse(field) : 0f;
if (ApiController.QrMap.ContainsKey(tag)) if (ApiController.QrMap.ContainsKey(tag))
{ {
CycleUiHelper.Alert("错误", $@"存在重复码值:{tag} 站点id为:{tagSite.id}"); FairyUiHelper.Alert("错误", $@"存在重复码值:{tag} 站点id为:{tagSite.id}");
return; return;
} }
+2 -2
View File
@@ -298,7 +298,7 @@ namespace StandardScene.CarTypes
RequiresPlatformConfirm = true, RequiresPlatformConfirm = true,
ConfirmMessage = "确定强制结束该车上的作业并下线?")] ConfirmMessage = "确定强制结束该车上的作业并下线?")]
[I18N.DocumentTranslation(Name = "Force Stop new", Description = "Stop car & reset clumsy", locale = "en")] [I18N.DocumentTranslation(Name = "Force Stop new", Description = "Stop car & reset clumsy", locale = "en")]
public new async void ForceStop() public override void ForceStop()
{ {
try try
{ {
@@ -327,7 +327,7 @@ namespace StandardScene.CarTypes
} }
catch (Exception ex) catch (Exception ex)
{ {
CycleUiHelper.Alert("错误", FairyUiHelper.Alert("错误",
$@"未能立即强制结束小车{name}({id}),原因:{ExceptionFormatter.FormatEx(ex)}"); $@"未能立即强制结束小车{name}({id}),原因:{ExceptionFormatter.FormatEx(ex)}");
} }
}) })