✨ feat(*): 添加扫码枪启动探活、全局退出助手及 README

- 添加扫码枪串口启动探活,检测端口占用并更新 UI 状态
- 新增 ShutdownHelper 安全停止 Host 扩展方法
- 新增 README.md 项目说明文档
- 更新 WorkflowHostedService 启动探活逻辑
- 补充 ShutdownHelper 与 WorkflowHostedService 单元测试
- 优化 DashboardPage 与 SystemSettingsPage 界面布局
- 调整 ModbusTcpPlcService 监控镜像读取逻辑
This commit is contained in:
2026-04-19 14:29:07 +08:00
parent 8f74e07c66
commit d70b94e904
26 changed files with 1564 additions and 827 deletions

View File

@@ -54,6 +54,7 @@ public partial class MainWindowViewModel : ObservableObject
Title = "Axi Omron PCB Check";
Logs = new ObservableCollection<UiLogEntry>();
RecentBoards = new ObservableCollection<BoardProcessRecord>();
PlcMonitorItems = new ObservableCollection<PlcMonitorItem>();
AdminUnlockStatus = "管理员功能已锁定";
Logs.CollectionChanged += OnLogsCollectionChanged;
@@ -77,6 +78,11 @@ public partial class MainWindowViewModel : ObservableObject
/// </summary>
public ObservableCollection<BoardProcessRecord> RecentBoards { get; }
/// <summary>
/// 获取 PLC 实时监控集合。
/// </summary>
public ObservableCollection<PlcMonitorItem> PlcMonitorItems { get; }
/// <summary>
/// 获取最近运行日志集合(与 <see cref="Logs"/> 为同一集合,供 UI 绑定语义更清晰)。
/// </summary>
@@ -141,30 +147,12 @@ public partial class MainWindowViewModel : ObservableObject
[ObservableProperty]
private string _faultMessage = string.Empty;
/// <summary>
/// 获取或设置扫码次数。
/// </summary>
[ObservableProperty]
private int _scanTryCount;
/// <summary>
/// 获取或设置 SFTP 查询次数。
/// </summary>
[ObservableProperty]
private int _sftpTryCount;
/// <summary>
/// 获取或设置结果代码。
/// </summary>
[ObservableProperty]
private ushort _resultCode;
/// <summary>
/// 获取或设置报警代码。
/// </summary>
[ObservableProperty]
private ushort _alarmCode;
/// <summary>
/// 获取或设置最近触发时间。
/// </summary>
@@ -183,24 +171,6 @@ public partial class MainWindowViewModel : ObservableObject
[ObservableProperty]
private bool _isBusy;
/// <summary>
/// 获取或设置是否存在系统故障。
/// </summary>
[ObservableProperty]
private bool _isFaulted;
/// <summary>
/// 获取或设置是否已完成。
/// </summary>
[ObservableProperty]
private bool _isDone;
/// <summary>
/// 获取或设置是否已触发报警。
/// </summary>
[ObservableProperty]
private bool _isAlarmRaised;
/// <summary>
/// 获取或设置最近更新时间。
/// </summary>
@@ -219,12 +189,6 @@ public partial class MainWindowViewModel : ObservableObject
[ObservableProperty]
private int _todayErrorCount;
/// <summary>
/// 获取或设置当前活跃告警数量。
/// </summary>
[ObservableProperty]
private int _activeAlarmCount;
/// <summary>
/// 获取或设置最近一次异常日志的时间文本。
/// </summary>
@@ -430,27 +394,17 @@ public partial class MainWindowViewModel : ObservableObject
CurrentBarcode = snapshot.CurrentBarcode;
ResultDescription = snapshot.ResultDescription;
FaultMessage = snapshot.FaultMessage;
ScanTryCount = snapshot.ScanTryCount;
SftpTryCount = snapshot.SftpTryCount;
ResultCode = snapshot.ResultCode;
AlarmCode = snapshot.AlarmCode;
LastTriggeredAt = snapshot.LastTriggeredAt?.ToString("yyyy-MM-dd HH:mm:ss") ?? "-";
LastCompletedAt = snapshot.LastCompletedAt?.ToString("yyyy-MM-dd HH:mm:ss") ?? "-";
IsBusy = snapshot.IsBusy;
IsFaulted = snapshot.SystemFault;
IsDone = snapshot.ProcessDone;
IsAlarmRaised = snapshot.AlarmRaised;
ActiveAlarmCount = snapshot.AlarmRaised ? 1 : 0;
LastUpdatedAt = snapshot.LastUpdatedAt.ToString("yyyy-MM-dd HH:mm:ss");
}
/// <summary>
/// 当 <see cref="IsAlarmRaised"/> 发生变化时同步活跃告警计数。
/// </summary>
/// <param name="value">最新告警状态。</param>
partial void OnIsAlarmRaisedChanged(bool value)
{
ActiveAlarmCount = value ? 1 : 0;
PlcMonitorItems.Clear();
foreach (PlcMonitorItem item in snapshot.PlcMonitorItems)
{
PlcMonitorItems.Add(item.Clone());
}
}
/// <summary>