Files
OrpaonVision/OrpaonVision.SiteApp/ViewModels/MainWindowViewModel.cs
2026-04-06 22:04:05 +08:00

181 lines
5.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using OrpaonVision.SiteApp.Runtime.Services;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Media;
namespace OrpaonVision.SiteApp.ViewModels
{
/// <summary>
/// 运行端主窗口 ViewModel。
/// </summary>
public sealed class MainWindowViewModel : INotifyPropertyChanged
{
private readonly ICameraService _cameraService;
private readonly IInferenceService _inferenceService;
private readonly IRuleEngineService _ruleEngineService;
private readonly IRuntimeStateMachineService _runtimeStateMachineService;
private string _statusText = "准备就绪。";
private Brush _statusBrush = Brushes.DarkGreen;
private string _layerText = "1/1";
private string _inferenceText = "-";
private string _decisionText = "-";
/// <summary>
/// 构造函数。
/// </summary>
public MainWindowViewModel(
ICameraService cameraService,
IInferenceService inferenceService,
IRuleEngineService ruleEngineService,
IRuntimeStateMachineService runtimeStateMachineService)
{
_cameraService = cameraService;
_inferenceService = inferenceService;
_ruleEngineService = ruleEngineService;
_runtimeStateMachineService = runtimeStateMachineService;
RefreshSnapshot();
}
/// <summary>
/// 状态文本。
/// </summary>
public string StatusText
{
get => _statusText;
private set => SetProperty(ref _statusText, value);
}
/// <summary>
/// 状态颜色。
/// </summary>
public Brush StatusBrush
{
get => _statusBrush;
private set => SetProperty(ref _statusBrush, value);
}
/// <summary>
/// 当前层显示文本。
/// </summary>
public string LayerText
{
get => _layerText;
private set => SetProperty(ref _layerText, value);
}
/// <summary>
/// 最近一次推理结果。
/// </summary>
public string InferenceText
{
get => _inferenceText;
private set => SetProperty(ref _inferenceText, value);
}
/// <summary>
/// 最近一次规则判定结果。
/// </summary>
public string DecisionText
{
get => _decisionText;
private set => SetProperty(ref _decisionText, value);
}
/// <summary>
/// 执行一轮采集-推理-规则判定。
/// </summary>
public void RunOneCycle()
{
var snapshot = _runtimeStateMachineService.GetSnapshot();
var captureResult = _cameraService.CaptureFrame();
if (!captureResult.Succeeded || captureResult.Data is null)
{
SetError("相机采图失败。", captureResult.Message);
return;
}
var predictResult = _inferenceService.Predict(captureResult.Data);
if (!predictResult.Succeeded || predictResult.Data is null)
{
SetError("模型推理失败。", predictResult.Message);
return;
}
var inference = predictResult.Data;
InferenceText = $"{inference.Label} (置信度: {inference.Confidence:P0})";
var decisionResult = _ruleEngineService.Evaluate(snapshot.CurrentLayer, inference);
if (!decisionResult.Succeeded || decisionResult.Data is null)
{
SetError("规则判定失败。", decisionResult.Message);
return;
}
var decision = decisionResult.Data;
DecisionText = $"{decision.Code} - {decision.Message}";
StatusBrush = decision.IsPass ? Brushes.DarkGreen : Brushes.OrangeRed;
StatusText = decision.IsPass ? "当前层判定通过。" : "当前层判定 NG请人工复核。";
}
/// <summary>
/// 推进到下一层。
/// </summary>
public void MoveToNextLayer()
{
var moveResult = _runtimeStateMachineService.MoveToNextLayer();
if (!moveResult.Succeeded)
{
SetError("状态机切层失败。", moveResult.Message);
return;
}
RefreshSnapshot();
StatusBrush = Brushes.DarkGreen;
StatusText = moveResult.Message;
}
/// <summary>
/// 重置运行状态。
/// </summary>
public void ResetRuntime()
{
_runtimeStateMachineService.Reset();
InferenceText = "-";
DecisionText = "-";
RefreshSnapshot();
StatusBrush = Brushes.DarkGreen;
StatusText = "运行状态已重置。";
}
/// <inheritdoc />
public event PropertyChangedEventHandler? PropertyChanged;
private void RefreshSnapshot()
{
var snapshot = _runtimeStateMachineService.GetSnapshot();
LayerText = $"{snapshot.CurrentLayer}/{snapshot.TotalLayers}";
}
private void SetError(string title, string message)
{
StatusBrush = Brushes.OrangeRed;
StatusText = $"{title} {message}";
}
private void SetProperty<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value))
{
return;
}
field = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}