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 _allDieTransferPathItems = new List(); private ObservableCollection _dieTransferPathItems = new ObservableCollection(); /// /// 界面上显示的传输路径集合 /// public ObservableCollection 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(); _cameraAxisViewModel.CameraAxisDevices.HardwareDeviceList = hardwareManager.CameraAxisManager.TopCameraAxisDevices; var _paramlist = parameterManager as IParamList; _dieBondingManualSetting = _paramlist.GetParameter(); Pagination.PageChanged += (s, e) => LoadData(); LoadData(); } private void LoadData() { // 如果数据源为空,清空并返回 if (_allDieTransferPathItems == null || !_allDieTransferPathItems.Any()) { DieTransferPathItems = new ObservableCollection(); 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(_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 CreateDieCandidates(RegionModel region) { List dieCandidates = new List(); 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 CreatePadCandidates(RegionModel region) { List padCandidates = new List(); 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 ConvertToPathItems(DieTransferPathPlan pathPlan) { List pathItems = new List(); 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; } } }