247 lines
9.9 KiB
C#
247 lines
9.9 KiB
C#
using MainShell.Common;
|
||
using MainShell.Hardware;
|
||
using MainShell.Manual.Model;
|
||
using MainShell.Models;
|
||
using MainShell.Models.Wafer;
|
||
using MainShell.ParaSetting.Model;
|
||
using MainShell.Process;
|
||
using MainShell.ProcessResult;
|
||
using MainShell.Recipe.BaseBoard.Model;
|
||
using MainShell.Recipe.Models;
|
||
using MainShell.Resources.CustomControl;
|
||
using MaxwellFramework.Core.Interfaces;
|
||
using MwFramework.ManagerService;
|
||
using Stylet;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Collections.ObjectModel;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace MainShell.Manual.ViewModel
|
||
{
|
||
public class DieBondingViewModel : OperateViewModelBase
|
||
{
|
||
private readonly RecipeManager _recipeManager;
|
||
private readonly IEventAggregator _eventAggregator; // 引用 EventAggregator
|
||
private readonly ProcessResultManager _processResultManager;
|
||
private readonly HardwareManager _hardwareManager;
|
||
private readonly IDieTransferPathGenerator _dieTransferPathGenerator;
|
||
|
||
|
||
private List<DieTransferPathItem> _allDieTransferPathItems = new List<DieTransferPathItem>();
|
||
|
||
private ObservableCollection<DieTransferPathItem> _dieTransferPathItems = new ObservableCollection<DieTransferPathItem>();
|
||
/// <summary>
|
||
/// 界面上显示的传输路径集合
|
||
/// </summary>
|
||
public ObservableCollection<DieTransferPathItem> DieTransferPathItems
|
||
{
|
||
get { return _dieTransferPathItems; }
|
||
set { SetAndNotify(ref _dieTransferPathItems, value); }
|
||
}
|
||
|
||
private DieTransferPathItem _selectedDieTransferPathItem;
|
||
public DieTransferPathItem SelectedDieTransferPathItem
|
||
{
|
||
get => _selectedDieTransferPathItem;
|
||
set => SetAndNotify(ref _selectedDieTransferPathItem, value);
|
||
}
|
||
|
||
private readonly DieBondingManualSetting _dieBondingManualSetting;
|
||
public DieBondingManualSysItem DieBondingManualSysItem => _dieBondingManualSetting.DieBondingManualSysItem;
|
||
public PaginationViewModel Pagination { get; } = new PaginationViewModel();
|
||
public DieBondingViewModel(IEventAggregator eventAggregator, RecipeManager recipeManager,
|
||
ProcessResultManager processResultManager, HardwareManager hardwareManager, IDieTransferPathGenerator dieTransferPathGenerator, IParameterManager parameterManager)
|
||
{
|
||
_eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator));
|
||
_recipeManager = recipeManager ?? throw new ArgumentNullException(nameof(recipeManager));
|
||
_processResultManager = processResultManager ?? throw new ArgumentNullException(nameof(processResultManager));
|
||
_hardwareManager = hardwareManager ?? throw new ArgumentNullException(nameof(hardwareManager));
|
||
_dieTransferPathGenerator = dieTransferPathGenerator ?? throw new ArgumentNullException(nameof(dieTransferPathGenerator));
|
||
|
||
_cameraAxisViewModel = IoC.Get<Common.Display.ViewModel.CameraAxisViewModel>();
|
||
_cameraAxisViewModel.CameraAxisDevices.HardwareDeviceList = hardwareManager.CameraAxisManager.TopCameraAxisDevices;
|
||
|
||
var _paramlist = parameterManager as IParamList;
|
||
|
||
_dieBondingManualSetting = _paramlist.GetParameter<DieBondingManualSetting>();
|
||
|
||
Pagination.PageChanged += (s, e) => LoadData();
|
||
|
||
LoadData();
|
||
}
|
||
|
||
private void LoadData()
|
||
{
|
||
// 如果数据源为空,清空并返回
|
||
if (_allDieTransferPathItems == null || !_allDieTransferPathItems.Any())
|
||
{
|
||
DieTransferPathItems = new ObservableCollection<DieTransferPathItem>();
|
||
Pagination.TotalItems = 0;
|
||
return;
|
||
}
|
||
|
||
// 1. 先更新总数(这很重要,因为TotalPages依赖它)
|
||
Pagination.TotalItems = _allDieTransferPathItems.Count();
|
||
|
||
// 2. 自动修正页码:如果当前页超过了新的总页数,强制跳到最后一页
|
||
// 注意:修改 Pagination.CurrentPage 会再次触发 PageChanged -> LoadData,
|
||
// 所以我们需要防止无限递归,或者只在必要时修正。
|
||
// 在这里,简单的方式是计算 offset 时进行钳制,而不强行修改 CurrentPage 属性(取决于你的需求)
|
||
// 或者更好的是:
|
||
if (Pagination.CurrentPage > Pagination.TotalItems && Pagination.TotalItems > 0)
|
||
{
|
||
// 如果这里修改 CurrentPage 触发 LoadData,则本次 LoadData 可以直接中断
|
||
Pagination.CurrentPage = Pagination.TotalPages;
|
||
return;
|
||
}
|
||
|
||
// 3. 安全计算 Offset
|
||
int safePage = Math.Min(Pagination.CurrentPage, Pagination.TotalPages);
|
||
safePage = Math.Max(1, safePage); // 确保至少为1
|
||
|
||
int offset = (safePage - 1) * Pagination.PageSize;
|
||
int limit = Pagination.PageSize;
|
||
|
||
// 4. 重置集合
|
||
DieTransferPathItems = new ObservableCollection<DieTransferPathItem>(_allDieTransferPathItems.Skip(offset).Take(limit));
|
||
}
|
||
|
||
public async Task SaveDieBondingSetAsync()
|
||
{
|
||
bool success = await Loading.RunAsync(async (token, progress) =>
|
||
{
|
||
_dieBondingManualSetting.Write();
|
||
|
||
}, "保存参数...",isIndeterminate:true,canCancel:false);
|
||
}
|
||
|
||
public Task GenerateTransPathAsync()
|
||
{
|
||
DieTransferPathRequest pathRequest = CreatePathRequest();
|
||
DieTransferPathPlan pathPlan = _dieTransferPathGenerator.Generate(pathRequest);
|
||
_allDieTransferPathItems = ConvertToPathItems(pathPlan);
|
||
Pagination.CurrentPage = 1;
|
||
LoadData();
|
||
return Task.CompletedTask;
|
||
}
|
||
|
||
private DieTransferPathRequest CreatePathRequest()
|
||
{
|
||
DieTransferPathRequest pathRequest = new DieTransferPathRequest();
|
||
pathRequest.DieRegion = DieBondingManualSysItem.DieRegion;
|
||
pathRequest.SubstrateRegion = DieBondingManualSysItem.SubstrateRegion;
|
||
pathRequest.TransPathType = DieBondingManualSysItem.TransPathType;
|
||
pathRequest.PadRowDirectionStrategy = DieBondingManualSysItem.PadRowDirectionStrategy;
|
||
pathRequest.DieRowDirectionStrategy = DieBondingManualSysItem.DieRowDirectionStrategy;
|
||
pathRequest.SkipNgDie = true;
|
||
pathRequest.DieCandidates = CreateDieCandidates(DieBondingManualSysItem.DieRegion);
|
||
pathRequest.PadCandidates = CreatePadCandidates(DieBondingManualSysItem.SubstrateRegion);
|
||
return pathRequest;
|
||
}
|
||
|
||
private List<Die> CreateDieCandidates(RegionModel region)
|
||
{
|
||
List<Die> dieCandidates = new List<Die>();
|
||
if (region == null)
|
||
{
|
||
return dieCandidates;
|
||
}
|
||
|
||
for (int row = region.StartRow; row <= region.EndRow; row++)
|
||
{
|
||
for (int column = region.StartCol; column <= region.EndCol; column++)
|
||
{
|
||
Die die = new Die();
|
||
die.Row = row;
|
||
die.Column = column;
|
||
die.X = column;
|
||
die.Y = row;
|
||
die.Status = DieStatus.Normal;
|
||
dieCandidates.Add(die);
|
||
}
|
||
}
|
||
|
||
return dieCandidates;
|
||
}
|
||
|
||
private List<Pad> CreatePadCandidates(RegionModel region)
|
||
{
|
||
List<Pad> padCandidates = new List<Pad>();
|
||
if (region == null)
|
||
{
|
||
return padCandidates;
|
||
}
|
||
|
||
for (int row = region.StartRow; row <= region.EndRow; row++)
|
||
{
|
||
for (int column = region.StartCol; column <= region.EndCol; column++)
|
||
{
|
||
Pad pad = new Pad();
|
||
pad.Row = row;
|
||
pad.Column = column;
|
||
pad.X = column;
|
||
pad.Y = row;
|
||
|
||
SubstratePoint substratePoint;
|
||
if (TryGetSubstratePoint(row, column, out substratePoint))
|
||
{
|
||
pad.X = substratePoint.X;
|
||
pad.Y = substratePoint.Y;
|
||
}
|
||
|
||
padCandidates.Add(pad);
|
||
}
|
||
}
|
||
|
||
return padCandidates;
|
||
}
|
||
|
||
private bool TryGetSubstratePoint(int row, int column, out SubstratePoint substratePoint)
|
||
{
|
||
substratePoint = default(SubstratePoint);
|
||
|
||
SubstratePoint[,] substratePoints = _recipeManager.CurrentSubstrateRecipe != null
|
||
? _recipeManager.CurrentSubstrateRecipe.SubstratePoints
|
||
: null;
|
||
if (substratePoints == null)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
int rowIndex = row - 1;
|
||
int columnIndex = column - 1;
|
||
if (rowIndex < 0 || rowIndex >= substratePoints.GetLength(0) || columnIndex < 0 || columnIndex >= substratePoints.GetLength(1))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
substratePoint = substratePoints[rowIndex, columnIndex];
|
||
return true;
|
||
}
|
||
|
||
private static List<DieTransferPathItem> ConvertToPathItems(DieTransferPathPlan pathPlan)
|
||
{
|
||
List<DieTransferPathItem> pathItems = new List<DieTransferPathItem>();
|
||
if (pathPlan == null || pathPlan.Steps == null)
|
||
{
|
||
return pathItems;
|
||
}
|
||
|
||
foreach (DieTransferPathStep pathStep in pathPlan.Steps)
|
||
{
|
||
DieTransferPathItem pathItem = DieTransferPathItem.FromPathStep(pathStep);
|
||
if (pathItem != null)
|
||
{
|
||
pathItems.Add(pathItem);
|
||
}
|
||
}
|
||
|
||
return pathItems;
|
||
}
|
||
}
|
||
}
|