桌面端快检记录新增列表及同步mes

This commit is contained in:
2026-06-22 17:38:49 +08:00
parent 3bce685f3a
commit efcd73a565
37 changed files with 2481 additions and 416 deletions

View File

@@ -10,9 +10,12 @@ using Prism.Events;
using Prism.Mvvm;
using Prism.Navigation;
using SkiaSharp;
using System.Collections.ObjectModel;
using System.Threading;
using YY.Admin.Core;
@@ -165,11 +168,11 @@ public class QuickTestInspectRowViewModel : BindableBase
/// <summary>胶料快检记录操作台 ViewModel密炼计划、实验标准均读本地缓存</summary>
public class RubberQuickTestOperationViewModel : BaseViewModel
public class RubberQuickTestOperationViewModel : BaseViewModel, INavigationAware
{
private readonly IRubberQuickTestOperationService _operationService;
private readonly IRubberQuickTestRecordService _recordService;
private readonly IMixingProductionPlanService _planService;
@@ -177,6 +180,12 @@ public class RubberQuickTestOperationViewModel : BaseViewModel
private readonly Random _rnd = new();
private bool _saveInProgress;
private string? _loadedDetailLocalId;
private string? _loadedDetailMesId;
private int _navigationApplyVersion;
private List<MesXslMixingProductionPlan> _allPlans = new();
private List<MesXslRubberQuickTestStd> _allStds = new();
@@ -200,7 +209,7 @@ public class RubberQuickTestOperationViewModel : BaseViewModel
public RubberQuickTestOperationViewModel(
IRubberQuickTestOperationService operationService,
IRubberQuickTestRecordService recordService,
IMixingProductionPlanService planService,
@@ -212,7 +221,7 @@ public class RubberQuickTestOperationViewModel : BaseViewModel
{
_operationService = operationService;
_recordService = recordService;
_planService = planService;
@@ -228,7 +237,7 @@ public class RubberQuickTestOperationViewModel : BaseViewModel
RemoveInspectRowCommand = new DelegateCommand(() => RemoveInspectRow(SelectedInspectRow), () => SelectedInspectRow != null);
SaveCommand = new DelegateCommand(async () => await SaveAsync(), () => InspectRows.Count > 0);
SaveCommand = new DelegateCommand(async () => await SaveAsync(), () => CanSave);
RefreshPlansCommand = new DelegateCommand(async () => await LoadLocalDataAsync(showSuccess: true));
@@ -259,13 +268,104 @@ public class RubberQuickTestOperationViewModel : BaseViewModel
_stdChangedToken = _eventAggregator.GetEvent<RubberQuickTestStdChangedEvent>()
.Subscribe(async _ => await ReloadLocalDataQuietAsync(), ThreadOption.UIThread);
_ = LoadLocalDataAsync(showSuccess: false);
RecalculateOverallInspectResult();
}
private bool _isReadOnly;
public bool IsReadOnly
{
get => _isReadOnly;
private set
{
if (!SetProperty(ref _isReadOnly, value)) return;
RaisePropertyChanged(nameof(IsEditable));
RaisePropertyChanged(nameof(ShowSaveButton));
NotifySaveStateChanged();
InspectColumnsChanged?.Invoke();
}
}
public bool IsEditable => !IsReadOnly;
public bool ShowSaveButton => !IsReadOnly;
public bool CanSave => InspectRows.Count > 0 && !_saveInProgress && !IsReadOnly;
private void NotifySaveStateChanged()
{
RaisePropertyChanged(nameof(CanSave));
SaveCommand.RaiseCanExecuteChanged();
}
protected override void OnIsLoadingChanged()
{
base.OnIsLoadingChanged();
NotifySaveStateChanged();
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
_ = ApplyNavigationAsync(navigationContext.Parameters);
}
private async Task ApplyNavigationAsync(INavigationParameters parameters)
{
var version = Interlocked.Increment(ref _navigationApplyVersion);
if (parameters.TryGetValue<bool>("readOnly", out var readOnly) && readOnly)
{
if (parameters.TryGetValue<string>("localId", out var localId) && !string.IsNullOrWhiteSpace(localId))
{
_loadedDetailLocalId = localId;
_loadedDetailMesId = null;
await LoadFromLocalItemAsync(localId);
return;
}
if (parameters.TryGetValue<string>("mesId", out var mesId) && !string.IsNullOrWhiteSpace(mesId))
{
_loadedDetailMesId = mesId;
_loadedDetailLocalId = null;
await LoadFromMesIdAsync(mesId);
return;
}
}
if (version != _navigationApplyVersion) return;
_loadedDetailLocalId = null;
_loadedDetailMesId = null;
IsReadOnly = false;
ResetFormForNewEntry();
await LoadLocalDataAsync(showSuccess: false);
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
var parameters = navigationContext.Parameters;
if (parameters.TryGetValue<bool>("readOnly", out var readOnly) && readOnly)
{
if (parameters.TryGetValue<string>("localId", out var localId) && !string.IsNullOrWhiteSpace(localId))
return IsReadOnly && string.Equals(_loadedDetailLocalId, localId, StringComparison.OrdinalIgnoreCase);
if (parameters.TryGetValue<string>("mesId", out var mesId) && !string.IsNullOrWhiteSpace(mesId))
return IsReadOnly && string.Equals(_loadedDetailMesId, mesId, StringComparison.OrdinalIgnoreCase);
return false;
}
return !IsReadOnly && _loadedDetailLocalId == null && _loadedDetailMesId == null;
}
private void ResetFormForNewEntry()
{
RecordNo = null;
TrainNo = null;
InspectTimesText = "1";
ClearPlanAndStdSelection();
RecalculateOverallInspectResult();
NotifySaveStateChanged();
}
public void OnNavigatedFrom(NavigationContext navigationContext) { }
private static string ResolveInspectorDisplay()
@@ -648,8 +748,8 @@ public class RubberQuickTestOperationViewModel : BaseViewModel
private async Task ReloadLocalDataQuietAsync()
{
if (IsReadOnly) return;
try
@@ -1070,7 +1170,7 @@ public class RubberQuickTestOperationViewModel : BaseViewModel
InspectRows.Add(row);
SaveCommand.RaiseCanExecuteChanged();
NotifySaveStateChanged();
RecalculateOverallInspectResult();
@@ -1090,7 +1190,7 @@ public class RubberQuickTestOperationViewModel : BaseViewModel
RenumberInspectRows();
SaveCommand.RaiseCanExecuteChanged();
NotifySaveStateChanged();
RecalculateOverallInspectResult();
@@ -1099,145 +1199,90 @@ public class RubberQuickTestOperationViewModel : BaseViewModel
private async Task SaveAsync()
{
if (_saveInProgress) return;
if (string.IsNullOrWhiteSpace(TrainNo))
{
Growl.Warning("请填写车次");
return;
}
if (SelectedPlan == null)
{
Growl.Warning("请选择密炼计划");
return;
}
if (string.IsNullOrWhiteSpace(RubberMaterialName))
{
Growl.Warning("请先选择密炼计划以带出胶料名称");
return;
}
if (SelectedStd == null || _currentStd == null)
{
Growl.Warning("请选择实验标准");
return;
}
if (InspectRows.Any(r => r.InspectResultText == "待填写" || string.IsNullOrWhiteSpace(r.InspectResultText)))
{
Growl.Warning("请手填全部检验行的检测值后再保存");
return;
}
if (!TryParseInspectTimes(out var inspectTimes, out var inspectTimesError))
{
Growl.Warning(inspectTimesError);
return;
}
var lineList = BuildAveragedLineList();
if (lineList.Count == 0)
{
Growl.Warning("无法根据试验结果计算明细数据");
return;
}
var rawLineList = BuildRawLineList();
if (rawLineList.Count == 0)
{
Growl.Warning("无法生成试验结果原始数据");
return;
}
var user = AppSession.CurrentUser;
IsLoading = true;
_saveInProgress = true;
NotifySaveStateChanged();
try
{
if (string.IsNullOrWhiteSpace(TrainNo))
{
Growl.Warning("请填写车次");
return;
}
var record = BuildSaveRecord(lineList, rawLineList, inspectTimes, user);
if (SelectedPlan == null)
{
Growl.Warning("请选择密炼计划");
return;
}
var recordNo = await _operationService.SaveRecordAsync(record);
if (string.IsNullOrWhiteSpace(RubberMaterialName))
{
Growl.Warning("请先选择密炼计划以带出胶料名称");
return;
}
RecordNo = recordNo;
if (SelectedStd == null || _currentStd == null)
{
Growl.Warning("请选择实验标准");
return;
}
Growl.Success(string.IsNullOrWhiteSpace(recordNo)
if (InspectRows.Any(r => r.InspectResultText == "待填写" || string.IsNullOrWhiteSpace(r.InspectResultText)))
{
Growl.Warning("请手填全部检验行的检测值后再保存");
return;
}
? "胶料快检记录已保存到 MES"
if (!TryParseInspectTimes(out var inspectTimes, out var inspectTimesError))
{
Growl.Warning(inspectTimesError);
return;
}
: $"胶料快检记录已保存,单号:{recordNo}");
var rawLineList = BuildRawLineList();
if (rawLineList.Count == 0)
{
Growl.Warning("无法生成试验结果原始数据");
return;
}
var stdLineList = BuildStdLineList();
if (stdLineList.Count == 0)
{
Growl.Warning("无法生成数据标准明细");
return;
}
var chartPointList = BuildChartPointList();
var user = AppSession.CurrentUser;
IsLoading = true;
var record = BuildSaveRecord(stdLineList, rawLineList, chartPointList, inspectTimes, user);
var saved = await _recordService.SaveAsync(record);
RecordNo = saved.Record.RecordNo;
var syncHint = saved.SyncStatus == "Synced" ? "并已同步到 MES" : "MES 同步待重试)";
Growl.Success(string.IsNullOrWhiteSpace(RecordNo)
? $"胶料快检记录已保存到本地{syncHint}"
: $"胶料快检记录已保存,快检记录号:{RecordNo}{syncHint}");
InspectRows.Clear();
SaveCommand.RaiseCanExecuteChanged();
NotifySaveStateChanged();
}
catch (Exception ex)
{
Growl.Error($"保存失败:{ex.Message}");
}
finally
{
IsLoading = false;
_saveInProgress = false;
NotifySaveStateChanged();
}
}
@@ -1432,10 +1477,12 @@ public class RubberQuickTestOperationViewModel : BaseViewModel
private MesXslRubberQuickTestRecord BuildSaveRecord(
List<MesXslRubberQuickTestRecordLine> lineList,
List<MesXslRubberQuickTestRecordStdLine> stdLineList,
List<MesXslRubberQuickTestRecordRawLine> rawLineList,
List<MesXslRubberQuickTestRecordChartPoint> chartPointList,
int inspectTimes,
SysUser? user)
@@ -1446,13 +1493,19 @@ public class RubberQuickTestOperationViewModel : BaseViewModel
{
LineList = lineList,
StdLineList = stdLineList,
RawLineList = rawLineList,
ChartPointList = chartPointList,
InspectTime = DateTime.Now,
InspectResult = OverallInspectResultCode
CreateTime = DateTime.Now,
InspectResult = OverallInspectResultCode,
RecordNo = _recordService.GenerateRecordNo(RubberMaterialName ?? string.Empty)
};
@@ -1470,6 +1523,26 @@ public class RubberQuickTestOperationViewModel : BaseViewModel
record.StdId = _currentStd.Id;
if (!string.IsNullOrWhiteSpace(_currentStd?.StdName))
record.StdName = _currentStd.StdName;
if (!string.IsNullOrWhiteSpace(_currentStd?.TestMethodId))
record.TestMethodId = _currentStd.TestMethodId;
if (!string.IsNullOrWhiteSpace(TestMethodName))
record.TestMethodName = TestMethodName;
if (!string.IsNullOrWhiteSpace(_currentStd?.QuickTestTypeId))
record.QuickTestTypeId = _currentStd.QuickTestTypeId;
if (!string.IsNullOrWhiteSpace(_currentStd?.QuickTestTypeName))
record.QuickTestTypeName = _currentStd.QuickTestTypeName;
if (!string.IsNullOrWhiteSpace(_selectedPlan?.MachineId))
@@ -1502,9 +1575,9 @@ public class RubberQuickTestOperationViewModel : BaseViewModel
if (!string.IsNullOrWhiteSpace(_selectedPlan?.PlanMaterialNo))
if (!string.IsNullOrWhiteSpace(_selectedPlan?.PlanNo))
record.ProductionPlanNo = _selectedPlan.PlanMaterialNo;
record.ProductionPlanNo = _selectedPlan.PlanNo;
@@ -1528,6 +1601,169 @@ public class RubberQuickTestOperationViewModel : BaseViewModel
}
private List<MesXslRubberQuickTestRecordStdLine> BuildStdLineList()
{
var lines = new List<MesXslRubberQuickTestRecordStdLine>();
int sort = 0;
foreach (var col in DataPointColumns)
{
lines.Add(new MesXslRubberQuickTestRecordStdLine
{
DataPointId = col.DataPointId,
PointName = col.PointName,
LowerLimit = col.LowerLimit,
LowerWarn = col.LowerWarn,
TargetValue = col.TargetValue,
UpperWarn = col.UpperWarn,
UpperLimit = col.UpperLimit,
SortNo = sort++
});
}
return lines;
}
private List<MesXslRubberQuickTestRecordChartPoint> BuildChartPointList()
{
var points = new List<MesXslRubberQuickTestRecordChartPoint>();
int sort = 0;
for (int i = 0; i < ChartPointCount && i < UpperTempValues.Count; i++)
{
points.Add(new MesXslRubberQuickTestRecordChartPoint
{
TimeMin = (decimal)(UpperTempValues[i].X ?? ChartTimeMinutes[i]),
UpperTemp = UpperTempValues[i].Y.HasValue ? (decimal)UpperTempValues[i].Y!.Value : null,
LowerTemp = i < LowerTempValues.Count && LowerTempValues[i].Y.HasValue ? (decimal)LowerTempValues[i].Y!.Value : null,
TorqueS = i < TorqueValues.Count && TorqueValues[i].Y.HasValue ? (decimal)TorqueValues[i].Y!.Value : null,
SortNo = sort++
});
}
return points;
}
private async Task LoadFromLocalItemAsync(string localId)
{
var item = _recordService.GetByLocalId(localId);
if (item == null)
{
Growl.Warning("未找到快检记录");
return;
}
await ApplyRecordDetailAsync(item.Record);
}
private async Task LoadFromMesIdAsync(string mesId)
{
var record = await _recordService.GetByIdAsync(mesId);
if (record == null)
{
Growl.Warning("未找到快检记录");
return;
}
await ApplyRecordDetailAsync(record);
}
private async Task ApplyRecordDetailAsync(MesXslRubberQuickTestRecord r)
{
IsReadOnly = true;
RecordNo = r.RecordNo;
MixingDate = r.ProductionDate ?? DateTime.Today;
SelectedMachine = r.ProdEquipmentName;
TrainNo = r.TrainNo;
InspectTimesText = r.InspectTimes?.ToString() ?? "1";
InspectorDisplay = r.InspectorRealname ?? ResolveInspectorDisplay();
OverallInspectResultCode = r.InspectResult ?? "0";
OverallInspectResultDisplay = string.Equals(r.InspectResult, "1", StringComparison.Ordinal) ? "合格" : "不合格";
TestMethodName = r.TestMethodName;
MachineOptions.Clear();
if (!string.IsNullOrWhiteSpace(r.ProdEquipmentName))
MachineOptions.Add(r.ProdEquipmentName);
ShiftOptions.Clear();
var shift = new WorkShiftOption(r.WorkShift ?? "", r.WorkShift ?? "");
ShiftOptions.Add(shift);
SelectedShift = shift;
PlanOptions.Clear();
var plan = new MesXslMixingProductionPlan
{
PlanNo = r.ProductionPlanNo,
MaterialName = r.RubberMaterialName,
MachineName = r.ProdEquipmentName
};
PlanOptions.Add(plan);
_selectedPlan = plan;
RaisePropertyChanged(nameof(SelectedPlan));
RaisePropertyChanged(nameof(MachineName));
RaisePropertyChanged(nameof(RubberMaterialName));
StdOptions.Clear();
var std = new MesXslRubberQuickTestStd { Id = r.StdId, StdName = r.StdName, TestMethodName = r.TestMethodName };
StdOptions.Add(std);
_selectedStd = std;
RaisePropertyChanged(nameof(SelectedStd));
DataPointColumns.Clear();
InspectRows.Clear();
foreach (var sl in (r.StdLineList ?? new List<MesXslRubberQuickTestRecordStdLine>()).OrderBy(x => x.SortNo ?? 0))
{
DataPointColumns.Add(new MesXslRubberQuickTestStdLine
{
DataPointId = sl.DataPointId,
PointName = sl.PointName,
LowerLimit = sl.LowerLimit,
LowerWarn = sl.LowerWarn,
TargetValue = sl.TargetValue,
UpperWarn = sl.UpperWarn,
UpperLimit = sl.UpperLimit,
SortNo = sl.SortNo
});
}
InspectColumnsChanged?.Invoke();
var grouped = (r.RawLineList ?? new List<MesXslRubberQuickTestRecordRawLine>())
.GroupBy(x => x.RowNo ?? string.Empty)
.OrderBy(g => g.Key, StringComparer.Ordinal);
foreach (var g in grouped)
{
var row = new QuickTestInspectRowViewModel { RowNo = g.Key };
for (int i = 0; i < DataPointColumns.Count; i++)
{
var col = DataPointColumns[i];
var raw = g.FirstOrDefault(x => x.DataPointId == col.DataPointId || x.InspectItem == col.PointName);
var cell = new QuickTestInspectCellViewModel
{
DataPointId = col.DataPointId,
PointName = col.PointName ?? string.Empty,
LowerLimit = col.LowerLimit,
UpperLimit = col.UpperLimit,
Value = raw?.InspectValue
};
row.Cells.Add(cell);
}
row.RecalculateResult();
InspectRows.Add(row);
}
UpperTempValues.Clear();
LowerTempValues.Clear();
TorqueValues.Clear();
foreach (var pt in (r.ChartPointList ?? new List<MesXslRubberQuickTestRecordChartPoint>()).OrderBy(x => x.SortNo ?? 0))
{
var time = (double)(pt.TimeMin ?? 0);
if (pt.UpperTemp != null) UpperTempValues.Add(new ObservablePoint(time, (double)pt.UpperTemp.Value));
if (pt.LowerTemp != null) LowerTempValues.Add(new ObservablePoint(time, (double)pt.LowerTemp.Value));
if (pt.TorqueS != null) TorqueValues.Add(new ObservablePoint(time, (double)pt.TorqueS.Value));
}
if (UpperTempValues.Count > 0) UpperMoldTemp = UpperTempValues[^1].Y ?? 0;
if (LowerTempValues.Count > 0) LowerMoldTemp = LowerTempValues[^1].Y ?? 0;
if (TorqueValues.Count > 0) TorqueS = TorqueValues[^1].Y ?? 0;
await Task.CompletedTask;
}
private static Axis[] BuildTimeAxis() => new[]