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

247 lines
9.9 KiB
C#
Raw Permalink 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 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;
}
}
}