|
|
@@ -0,0 +1,268 @@
|
|
|
+using Prism.Commands;
|
|
|
+using Prism.Mvvm;
|
|
|
+using System;
|
|
|
+using System.Collections.ObjectModel;
|
|
|
+using System.IO;
|
|
|
+using System.Linq;
|
|
|
+using System.Text;
|
|
|
+using System.Threading.Tasks;
|
|
|
+using System.Windows;
|
|
|
+using TeamAAS_VP.Interfaces;
|
|
|
+using TeamAAS_VP.Models;
|
|
|
+using TeamAAS_VP.Models.Product;
|
|
|
+
|
|
|
+namespace TeamAAS_VP.ViewModels.Statistics
|
|
|
+{
|
|
|
+ public class LockResultRecoredQueryViewModel : BindableBase
|
|
|
+ {
|
|
|
+ private readonly IProductService _productService;
|
|
|
+ private readonly ISystemDatabaseService _systemDatabaseService;
|
|
|
+
|
|
|
+ public LockResultRecoredQueryViewModel(IProductService productService, ISystemDatabaseService systemDatabaseService)
|
|
|
+ {
|
|
|
+ _productService = productService;
|
|
|
+ _systemDatabaseService = systemDatabaseService;
|
|
|
+
|
|
|
+ PageSize = 20;
|
|
|
+ PageIndex = 1;
|
|
|
+
|
|
|
+ SearchCommand = new DelegateCommand(async () => await ExecuteSearchCommand(), CanSearch).ObservesProperty(() => SelectedProduct).ObservesProperty(() => StartDate).ObservesProperty(() => EndDate).ObservesProperty(() => IsSearching);
|
|
|
+ PrevPageCommand = new DelegateCommand(async () => { if (PageIndex>1) { PageIndex--; await ExecuteSearchCommand(); } }).ObservesProperty(() => PageIndex);
|
|
|
+ NextPageCommand = new DelegateCommand(async () => { if (PageIndex * PageSize < TotalCount) { PageIndex++; await ExecuteSearchCommand(); } }).ObservesProperty(() => PageIndex).ObservesProperty(() => TotalCount);
|
|
|
+ ExportCommand = new DelegateCommand(async () => await ExecuteExportCommand(), CanExport).ObservesProperty(() => Results).ObservesProperty(() => IsSearching);
|
|
|
+
|
|
|
+ AllProduct = new ObservableCollection<ProductModel>(_productService.GetAllProducts());
|
|
|
+ StartDate = DateTime.Now.Date;
|
|
|
+ EndDate = DateTime.Now.Date.AddDays(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ #region Properties
|
|
|
+ private ObservableCollection<ProductModel> _AllProduct;
|
|
|
+ public ObservableCollection<ProductModel> AllProduct
|
|
|
+ {
|
|
|
+ get { return _AllProduct; }
|
|
|
+ set { SetProperty(ref _AllProduct, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private ProductModel _SelectedProduct;
|
|
|
+ public ProductModel SelectedProduct
|
|
|
+ {
|
|
|
+ get { return _SelectedProduct; }
|
|
|
+ set { SetProperty(ref _SelectedProduct, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private DateTime? _StartDate;
|
|
|
+ public DateTime? StartDate
|
|
|
+ {
|
|
|
+ get { return _StartDate; }
|
|
|
+ set { SetProperty(ref _StartDate, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private DateTime? _EndDate;
|
|
|
+ public DateTime? EndDate
|
|
|
+ {
|
|
|
+ get { return _EndDate; }
|
|
|
+ set { SetProperty(ref _EndDate, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private int? _ScrewNumber;
|
|
|
+ public int? ScrewNumber
|
|
|
+ {
|
|
|
+ get { return _ScrewNumber; }
|
|
|
+ set { SetProperty(ref _ScrewNumber, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private string _ProductNumber;
|
|
|
+ public string ProductNumber
|
|
|
+ {
|
|
|
+ get { return _ProductNumber; }
|
|
|
+ set { SetProperty(ref _ProductNumber, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private ObservableCollection<LockResult> _Results = new ObservableCollection<LockResult>();
|
|
|
+ public ObservableCollection<LockResult> Results
|
|
|
+ {
|
|
|
+ get { return _Results; }
|
|
|
+ set { SetProperty(ref _Results, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private int _PageIndex;
|
|
|
+ public int PageIndex
|
|
|
+ {
|
|
|
+ get { return _PageIndex; }
|
|
|
+ set { SetProperty(ref _PageIndex, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private int _PageSize;
|
|
|
+ public int PageSize
|
|
|
+ {
|
|
|
+ get { return _PageSize; }
|
|
|
+ set { SetProperty(ref _PageSize, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private int _TotalCount;
|
|
|
+ public int TotalCount
|
|
|
+ {
|
|
|
+ get { return _TotalCount; }
|
|
|
+ set { SetProperty(ref _TotalCount, value); }
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool _IsSearching = false;
|
|
|
+ public bool IsSearching
|
|
|
+ {
|
|
|
+ get { return _IsSearching; }
|
|
|
+ set { SetProperty(ref _IsSearching, value); }
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region Commands
|
|
|
+ public DelegateCommand SearchCommand { get; private set; }
|
|
|
+ public DelegateCommand PrevPageCommand { get; private set; }
|
|
|
+ public DelegateCommand NextPageCommand { get; private set; }
|
|
|
+ public DelegateCommand ExportCommand { get; private set; }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ private bool CanSearch()
|
|
|
+ {
|
|
|
+ if (IsSearching) return false;
|
|
|
+ if (SelectedProduct == null && string.IsNullOrWhiteSpace(ProductNumber) && !ScrewNumber.HasValue)
|
|
|
+ return false;
|
|
|
+ if (!StartDate.HasValue || !EndDate.HasValue) return false;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool CanExport()
|
|
|
+ {
|
|
|
+ // allow export even if current page is empty; user may want to export all matching records
|
|
|
+ return !IsSearching && StartDate.HasValue && EndDate.HasValue && (SelectedProduct != null || !string.IsNullOrWhiteSpace(ProductNumber) || ScrewNumber.HasValue);
|
|
|
+ }
|
|
|
+
|
|
|
+ private async Task ExecuteSearchCommand()
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ IsSearching = true;
|
|
|
+
|
|
|
+ // determine time range (use full days)
|
|
|
+ var start = StartDate.HasValue ? StartDate.Value.Date : DateTime.MinValue;
|
|
|
+ var end = EndDate.HasValue ? EndDate.Value.Date.AddDays(1) : DateTime.MaxValue;
|
|
|
+
|
|
|
+ string productNumberFilter = null;
|
|
|
+ if (!string.IsNullOrWhiteSpace(ProductNumber)) productNumberFilter = ProductNumber.Trim();
|
|
|
+ // if SelectedProduct is selected, use its Name as productNumber? The user requested select product name then time range; productNumber precise search should still be supported
|
|
|
+ if (SelectedProduct != null && string.IsNullOrEmpty(productNumberFilter))
|
|
|
+ {
|
|
|
+ // assume SelectedProduct.Name correspond to ProductNumber field used when storing
|
|
|
+ productNumberFilter = SelectedProduct.Name;
|
|
|
+ }
|
|
|
+
|
|
|
+ int pageIndex = PageIndex < 1 ? 1 : PageIndex;
|
|
|
+ int pageSize = PageSize < 1 ? 20 : PageSize;
|
|
|
+
|
|
|
+ var res = await _systemDatabaseService.QueryLockResultsAsync(start, end, pageIndex, pageSize, productNumberFilter, ScrewNumber);
|
|
|
+ Results = new ObservableCollection<LockResult>(res.Items);
|
|
|
+ TotalCount = res.TotalCount;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ MessageBox.Show(ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ IsSearching = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private async Task ExecuteExportCommand()
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ IsSearching = true;
|
|
|
+
|
|
|
+ // determine time range
|
|
|
+ var start = StartDate.HasValue ? StartDate.Value.Date : DateTime.MinValue;
|
|
|
+ var end = EndDate.HasValue ? EndDate.Value.Date.AddDays(1) : DateTime.MaxValue;
|
|
|
+
|
|
|
+ string productNumberFilter = null;
|
|
|
+ if (!string.IsNullOrWhiteSpace(ProductNumber)) productNumberFilter = ProductNumber.Trim();
|
|
|
+ if (SelectedProduct != null && string.IsNullOrEmpty(productNumberFilter))
|
|
|
+ {
|
|
|
+ productNumberFilter = SelectedProduct.Name;
|
|
|
+ }
|
|
|
+
|
|
|
+ // fetch all matching records (not paged)
|
|
|
+ var all = await _systemDatabaseService.QueryAllLockResultsAsync(start, end, productNumberFilter, ScrewNumber);
|
|
|
+ if (all == null || !all.Any())
|
|
|
+ {
|
|
|
+ MessageBox.Show("没有找到符合条件的记录。", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ var saveFileDialog = new Microsoft.Win32.SaveFileDialog
|
|
|
+ {
|
|
|
+ FileName = $"LockResults_{DateTime.Now.ToString("yyyyMMddHHmmss")}.csv",
|
|
|
+ DefaultExt = ".csv",
|
|
|
+ Filter = "CSV Files (*.csv)|*.csv"
|
|
|
+ };
|
|
|
+ var result = saveFileDialog.ShowDialog();
|
|
|
+ if (result != true) return;
|
|
|
+ var path = saveFileDialog.FileName;
|
|
|
+
|
|
|
+ // write in streaming manner to support large sets
|
|
|
+ using (var sw = new StreamWriter(path, false, Encoding.UTF8))
|
|
|
+ {
|
|
|
+ sw.WriteLine("Id,Number,ProductNumber,Timestamp,LockTurns,LockTorque,LockDuration,LockPassed,ResultDetails,ScrewdriverProgramNumber,Pressure,TargetTorque,TargetTurnsUpperLimit,TargetTurnsLowerLimit,TargetLockSpeed,StartPositionX,StartPositionY,StartPositionZ,EndPositionZ,LockDescentSpeed,FeederNumber,NozzleNumber,OperatorName,ProductImagePath");
|
|
|
+ foreach (var r in all)
|
|
|
+ {
|
|
|
+ var line = string.Join(",",
|
|
|
+ EscapeCsv(r.Id.ToString()),
|
|
|
+ EscapeCsv(r.Number.ToString()),
|
|
|
+ EscapeCsv(r.ProductNumber),
|
|
|
+ EscapeCsv(r.Timestamp.ToString("yyyy-MM-dd HH:mm:ss")),
|
|
|
+ EscapeCsv(r.LockTurns.ToString()),
|
|
|
+ EscapeCsv(r.LockTorque.ToString()),
|
|
|
+ EscapeCsv(r.LockDuration.ToString()),
|
|
|
+ EscapeCsv(r.LockPassed ? "1" : "0"),
|
|
|
+ EscapeCsv(r.ResultDetails),
|
|
|
+ EscapeCsv(r.ScrewdriverProgramNumber.ToString()),
|
|
|
+ EscapeCsv(r.Pressure.ToString()),
|
|
|
+ EscapeCsv(r.TargetTorque.ToString()),
|
|
|
+ EscapeCsv(r.TargetTurnsUpperLimit.ToString()),
|
|
|
+ EscapeCsv(r.TargetTurnsLowerLimit.ToString()),
|
|
|
+ EscapeCsv(r.TargetLockSpeed.ToString()),
|
|
|
+ EscapeCsv(r.StartPositionX.ToString()),
|
|
|
+ EscapeCsv(r.StartPositionY.ToString()),
|
|
|
+ EscapeCsv(r.StartPositionZ.ToString()),
|
|
|
+ EscapeCsv(r.EndPositionZ.ToString()),
|
|
|
+ EscapeCsv(r.LockDescentSpeed.ToString()),
|
|
|
+ EscapeCsv(r.FeederNumber.ToString()),
|
|
|
+ EscapeCsv(r.NozzleNumber),
|
|
|
+ EscapeCsv(r.OperatorName),
|
|
|
+ EscapeCsv(r.ProductImagePath)
|
|
|
+ );
|
|
|
+ sw.WriteLine(line);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ MessageBox.Show(ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ IsSearching = false;
|
|
|
+ }
|
|
|
+ await Task.CompletedTask;
|
|
|
+ }
|
|
|
+
|
|
|
+ private string EscapeCsv(string s)
|
|
|
+ {
|
|
|
+ if (s == null) return "";
|
|
|
+ if (s.Contains(",") || s.Contains("\"") || s.Contains("\r") || s.Contains("\n"))
|
|
|
+ {
|
|
|
+ return "\"" + s.Replace("\"", "\"\"") + "\"";
|
|
|
+ }
|
|
|
+ return s;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|