Files
Shi.Ji e31d3560bb 添加 MX-PD-盘古 项目文件
将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
2026-05-18 11:43:09 +08:00

582 lines
20 KiB
C#

using MainShell.Common;
using MainShell.Hardware;
using MainShell.Log;
using MainShell.Manual.Model;
using MainShell.Models;
using MainShell.Motion;
using MainShell.Process;
using MainShell.ProcessResult;
using MainShell.Recipe.Models;
using MainShell.Resources.CustomControl;
using MwFramework.ManagerService;
using Stylet;
using StyletIoC;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using MW.WorkFlow;
namespace MainShell.Manual.ViewModel
{
public class DieRecheckDisplayItem : PropertyChangedBase
{
private int _stepIndex;
public int StepIndex
{
get { return _stepIndex; }
set { SetAndNotify(ref _stepIndex, value); }
}
private int _padRow;
public int PadRow
{
get { return _padRow; }
set { SetAndNotify(ref _padRow, value); }
}
private int _padColumn;
public int PadColumn
{
get { return _padColumn; }
set { SetAndNotify(ref _padColumn, value); }
}
private int _dieRow;
public int DieRow
{
get { return _dieRow; }
set { SetAndNotify(ref _dieRow, value); }
}
private int _dieColumn;
public int DieColumn
{
get { return _dieColumn; }
set { SetAndNotify(ref _dieColumn, value); }
}
private double _padX;
public double PadX
{
get { return _padX; }
set { SetAndNotify(ref _padX, value); }
}
private double _padY;
public double PadY
{
get { return _padY; }
set { SetAndNotify(ref _padY, value); }
}
private double _dieX;
public double DieX
{
get { return _dieX; }
set { SetAndNotify(ref _dieX, value); }
}
private double _dieY;
public double DieY
{
get { return _dieY; }
set { SetAndNotify(ref _dieY, value); }
}
private string _transPathType;
public string TransPathType
{
get { return _transPathType; }
set { SetAndNotify(ref _transPathType, value); }
}
private bool _isMissingBond;
public bool IsMissingBond
{
get { return _isMissingBond; }
set { SetAndNotify(ref _isMissingBond, value); }
}
private double _xError;
public double XError
{
get { return _xError; }
set { SetAndNotify(ref _xError, value); }
}
private double _yError;
public double YError
{
get { return _yError; }
set { SetAndNotify(ref _yError, value); }
}
private bool _isXThresholdExceeded;
public bool IsXThresholdExceeded
{
get { return _isXThresholdExceeded; }
set { SetAndNotify(ref _isXThresholdExceeded, value); }
}
private bool _isYThresholdExceeded;
public bool IsYThresholdExceeded
{
get { return _isYThresholdExceeded; }
set { SetAndNotify(ref _isYThresholdExceeded, value); }
}
private string _statusSummary;
public string StatusSummary
{
get { return _statusSummary; }
set { SetAndNotify(ref _statusSummary, value); }
}
}
public class DieRecheckFilterState : PropertyChangedBase
{
private enum DieRecheckFilterRule
{
None = 0,
MissingBondOnly,
XThresholdExceededOnly,
YThresholdExceededOnly,
XYThresholdExceededOnly
}
private DieRecheckFilterRule _selectedRule;
private bool _isUpdatingSelection;
public bool IsMissingBondRuleSelected
{
get { return _selectedRule == DieRecheckFilterRule.MissingBondOnly; }
set { SetSelectedRule(value, DieRecheckFilterRule.MissingBondOnly, nameof(IsMissingBondRuleSelected)); }
}
public bool IsXThresholdRuleSelected
{
get { return _selectedRule == DieRecheckFilterRule.XThresholdExceededOnly; }
set { SetSelectedRule(value, DieRecheckFilterRule.XThresholdExceededOnly, nameof(IsXThresholdRuleSelected)); }
}
public bool IsYThresholdRuleSelected
{
get { return _selectedRule == DieRecheckFilterRule.YThresholdExceededOnly; }
set { SetSelectedRule(value, DieRecheckFilterRule.YThresholdExceededOnly, nameof(IsYThresholdRuleSelected)); }
}
public bool IsXYThresholdRuleSelected
{
get { return _selectedRule == DieRecheckFilterRule.XYThresholdExceededOnly; }
set { SetSelectedRule(value, DieRecheckFilterRule.XYThresholdExceededOnly, nameof(IsXYThresholdRuleSelected)); }
}
private double _xThreshold = 0.01d;
public double XThreshold
{
get { return _xThreshold; }
set { SetAndNotify(ref _xThreshold, value); }
}
private double _yThreshold = 0.01d;
public double YThreshold
{
get { return _yThreshold; }
set { SetAndNotify(ref _yThreshold, value); }
}
public void ClearSelectedRule()
{
UpdateSelectedRule(DieRecheckFilterRule.None, null);
}
private void SetSelectedRule(bool isSelected, DieRecheckFilterRule targetRule, string propertyName)
{
if (_isUpdatingSelection)
{
return;
}
DieRecheckFilterRule newRule = isSelected ? targetRule : DieRecheckFilterRule.None;
UpdateSelectedRule(newRule, propertyName);
}
private void UpdateSelectedRule(DieRecheckFilterRule newRule, string propertyName)
{
if (_selectedRule == newRule)
{
if (!string.IsNullOrWhiteSpace(propertyName))
{
OnPropertyChanged(propertyName);
}
return;
}
_selectedRule = newRule;
_isUpdatingSelection = true;
try
{
OnPropertyChanged(nameof(IsMissingBondRuleSelected));
OnPropertyChanged(nameof(IsXThresholdRuleSelected));
OnPropertyChanged(nameof(IsYThresholdRuleSelected));
OnPropertyChanged(nameof(IsXYThresholdRuleSelected));
}
finally
{
_isUpdatingSelection = false;
}
}
}
public class DieRecheckViewModel : OperateViewModelBase
{
private readonly IEventAggregator _eventAggregator;
private readonly RecipeManager _recipeManager;
private readonly ProcessResultManager _processResultManager;
private readonly DieRecheckService _dieRecheckService;
private readonly SafeAxisMotion _safeAxisMotion;
private ObservableCollection<DieRecheckDisplayItem> _allPointResults = new ObservableCollection<DieRecheckDisplayItem>();
private List<DieRecheckDisplayItem> _filteredPointResults = new List<DieRecheckDisplayItem>();
private ObservableCollection<DieRecheckDisplayItem> _pointResults = new ObservableCollection<DieRecheckDisplayItem>();
public ObservableCollection<DieRecheckDisplayItem> PointResults
{
get { return _pointResults; }
set { SetAndNotify(ref _pointResults, value); }
}
public PaginationViewModel Pagination { get; } = new PaginationViewModel();
private RegionModel _recheckRegion = new RegionModel();
public RegionModel RecheckRegion
{
get { return _recheckRegion; }
set { SetAndNotify(ref _recheckRegion, value); }
}
private DieRecheckFilterState _filterState = new DieRecheckFilterState();
public DieRecheckFilterState FilterState
{
get { return _filterState; }
set { SetAndNotify(ref _filterState, value); }
}
private int _pointCount;
public int PointCount
{
get { return _pointCount; }
set { SetAndNotify(ref _pointCount, value); }
}
private int _filteredPointCount;
public int FilteredPointCount
{
get { return _filteredPointCount; }
set { SetAndNotify(ref _filteredPointCount, value); }
}
private DieRecheckDisplayItem _selectedPointResult;
public DieRecheckDisplayItem SelectedPointResult
{
get { return _selectedPointResult; }
set { SetAndNotify(ref _selectedPointResult, value); }
}
public DieRecheckViewModel(
IEventAggregator eventAggregator,
RecipeManager recipeManager,
ProcessResultManager processResultManager,
HardwareManager hardwareManager,
DieRecheckService dieRecheckService,
SafeAxisMotion safeAxisMotion)
{
_eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator));
_recipeManager = recipeManager ?? throw new ArgumentNullException(nameof(recipeManager));
_processResultManager = processResultManager ?? throw new ArgumentNullException(nameof(processResultManager));
if (hardwareManager == null)
{
throw new ArgumentNullException(nameof(hardwareManager));
}
_dieRecheckService = dieRecheckService ?? throw new ArgumentNullException(nameof(dieRecheckService));
_safeAxisMotion = safeAxisMotion ?? throw new ArgumentNullException(nameof(safeAxisMotion));
_cameraAxisViewModel = IoC.Get<Common.Display.ViewModel.CameraAxisViewModel>();
_cameraAxisViewModel.CameraAxisDevices.HardwareDeviceList = hardwareManager.CameraAxisManager.TopCameraAxisDevices;
FilterState.PropertyChanged += FilterState_PropertyChanged;
RecheckRegion.PropertyChanged += RecheckRegion_PropertyChanged;
Pagination.PageChanged += Pagination_PageChanged;
LoadCurrentPoints();
}
protected override void OnViewLoaded()
{
base.OnViewLoaded();
LoadCurrentPoints();
}
public async Task StartProcess()
{
WorkflowContext context = new WorkflowContext();
context[WorkflowContextKeys.EventAggregator] = _eventAggregator;
context[WorkflowContextKeys.RecipeManager] = _recipeManager;
context[WorkflowContextKeys.ProcessResultManager] = _processResultManager;
context[WorkflowContextKeys.WorkflowName] = ProcessFlowName.DieRecheckFlow;
WorkflowRunCompletedEventArgs result = await RunManualActivityAsync(
new DieRecheckActivity(ProcessFlowName.DieRecheckFlow, _dieRecheckService),
context,
false);
if (!IsWorkflowCompleted(result))
{
return;
}
LoadCurrentPoints();
}
public async Task MoveToSelectedPoint()
{
if (SelectedPointResult == null)
{
LocalizedMessageBox.Show(MessageKey.DieRecheckSelectedPointRequired, MessageKey.TitleWarning, MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
try
{
HardwareDevice selectedDevice = _cameraAxisViewModel.CameraAxisDevices != null
? _cameraAxisViewModel.CameraAxisDevices.SelectedHardwareDevice
: null;
if (selectedDevice == null || selectedDevice.AxisX == null || selectedDevice.AxisY == null)
{
LocalizedMessageBox.Show(MessageKey.DieRecheckMoveDeviceUnavailable, MessageKey.TitleWarning, MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
string moveMessage = $"DieRecheck move to point. StepIndex={SelectedPointResult.StepIndex}, PadX={SelectedPointResult.PadX:F4}, PadY={SelectedPointResult.PadY:F4}";
moveMessage.LogProcessInfo();
await Task.Run(() =>
_safeAxisMotion.SafeMove(
MotionMoveRequest.ForAxis(selectedDevice.AxisX, SelectedPointResult.PadX, source: nameof(DieRecheckViewModel), tags: new[] { "DieRecheck", "MoveToPoint", "AxisX" }),
MotionMoveRequest.ForAxis(selectedDevice.AxisY, SelectedPointResult.PadY, source: nameof(DieRecheckViewModel), tags: new[] { "DieRecheck", "MoveToPoint", "AxisY" })));
}
catch (Exception exception)
{
LogManager.LogSysError(exception);
MwMessageBox.Show(exception.Message, LanguageResourceHelper.GetString(MessageKey.TitleError), MessageBoxButton.OK, MessageBoxImage.Error);
}
}
public void ResetFilters()
{
FilterState.ClearSelectedRule();
FilterState.XThreshold = 0.01d;
FilterState.YThreshold = 0.01d;
ApplyFilters();
}
private void FilterState_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
UpdateThresholdFlags();
Pagination.CurrentPage = 1;
ApplyFilters();
}
private void RecheckRegion_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
Pagination.CurrentPage = 1;
ApplyFilters();
}
private void Pagination_PageChanged(object sender, EventArgs e)
{
LoadPagedData();
}
private void LoadCurrentPoints()
{
_allPointResults.Clear();
_filteredPointResults.Clear();
PointResults.Clear();
DieRecheckProcessResult processResult = _processResultManager.DieRecheckResult;
if (processResult == null || processResult.PointResults == null)
{
PointCount = 0;
FilteredPointCount = 0;
Pagination.TotalItems = 0;
return;
}
foreach (DieRecheckPointResult pointResult in processResult.PointResults)
{
_allPointResults.Add(new DieRecheckDisplayItem
{
StepIndex = pointResult.StepIndex,
PadRow = pointResult.PadRow,
PadColumn = pointResult.PadColumn,
DieRow = pointResult.DieRow,
DieColumn = pointResult.DieColumn,
PadX = pointResult.PadX,
PadY = pointResult.PadY,
DieX = pointResult.DieX,
DieY = pointResult.DieY,
TransPathType = pointResult.TransPathType,
IsMissingBond = pointResult.IsMissingBond,
XError = pointResult.XError,
YError = pointResult.YError
});
}
PointCount = _allPointResults.Count;
InitializeRegion();
UpdateThresholdFlags();
Pagination.CurrentPage = 1;
ApplyFilters();
}
private void InitializeRegion()
{
if (_allPointResults.Count == 0)
{
RecheckRegion.StartRow = 1;
RecheckRegion.StartCol = 1;
RecheckRegion.EndRow = 1;
RecheckRegion.EndCol = 1;
return;
}
RecheckRegion.StartRow = _allPointResults.Min(item => item.PadRow);
RecheckRegion.StartCol = _allPointResults.Min(item => item.PadColumn);
RecheckRegion.EndRow = Math.Max(RecheckRegion.StartRow, _allPointResults.Max(item => item.PadRow));
RecheckRegion.EndCol = Math.Max(RecheckRegion.StartCol, _allPointResults.Max(item => item.PadColumn));
}
private void UpdateThresholdFlags()
{
foreach (DieRecheckDisplayItem item in _allPointResults)
{
item.IsXThresholdExceeded = Math.Abs(item.XError) >= FilterState.XThreshold;
item.IsYThresholdExceeded = Math.Abs(item.YError) >= FilterState.YThreshold;
item.StatusSummary = BuildStatusSummary(item);
}
}
private string BuildStatusSummary(DieRecheckDisplayItem item)
{
Collection<string> tags = new Collection<string>();
if (item.IsMissingBond)
{
tags.Add(LanguageResourceHelper.GetString(MessageKey.DieRecheckStatusMissingBond));
}
if (item.IsXThresholdExceeded)
{
tags.Add(LanguageResourceHelper.Format(MessageKey.DieRecheckStatusXExceeded, item.XError));
}
if (item.IsYThresholdExceeded)
{
tags.Add(LanguageResourceHelper.Format(MessageKey.DieRecheckStatusYExceeded, item.YError));
}
if (tags.Count == 0)
{
tags.Add(LanguageResourceHelper.GetString(MessageKey.DieRecheckStatusOk));
}
return string.Join(" / ", tags);
}
private void ApplyFilters()
{
_filteredPointResults = _allPointResults.Where(MatchesFilters).ToList();
FilteredPointCount = _filteredPointResults.Count;
Pagination.TotalItems = FilteredPointCount;
if (Pagination.TotalItems == 0)
{
SelectedPointResult = null;
PointResults = new ObservableCollection<DieRecheckDisplayItem>();
return;
}
if (Pagination.CurrentPage > Pagination.TotalPages)
{
Pagination.CurrentPage = Pagination.TotalPages;
return;
}
LoadPagedData();
}
private void LoadPagedData()
{
if (_filteredPointResults == null || _filteredPointResults.Count == 0)
{
PointResults = new ObservableCollection<DieRecheckDisplayItem>();
SelectedPointResult = null;
return;
}
int safePage = Math.Max(1, Math.Min(Pagination.CurrentPage, Pagination.TotalPages));
int offset = (safePage - 1) * Pagination.PageSize;
int limit = Pagination.PageSize;
PointResults = new ObservableCollection<DieRecheckDisplayItem>(_filteredPointResults.Skip(offset).Take(limit));
if (SelectedPointResult != null && !PointResults.Contains(SelectedPointResult))
{
SelectedPointResult = null;
}
}
private bool MatchesFilters(DieRecheckDisplayItem item)
{
if (item == null)
{
return false;
}
bool isInRegion = item.PadRow >= RecheckRegion.StartRow
&& item.PadRow <= RecheckRegion.EndRow
&& item.PadColumn >= RecheckRegion.StartCol
&& item.PadColumn <= RecheckRegion.EndCol;
if (!isInRegion)
{
return false;
}
if (FilterState.IsMissingBondRuleSelected && !item.IsMissingBond)
{
return false;
}
if (FilterState.IsXYThresholdRuleSelected && !(item.IsXThresholdExceeded && item.IsYThresholdExceeded))
{
return false;
}
if (FilterState.IsXThresholdRuleSelected && !item.IsXThresholdExceeded)
{
return false;
}
if (FilterState.IsYThresholdRuleSelected && !item.IsYThresholdExceeded)
{
return false;
}
return true;
}
}
}