You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

569 lines
19 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using GalaSoft.MvvmLight;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using SlnMesnac.Model.domain;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using GalaSoft.MvvmLight.Command;
using SlnMesnac.Business;
using SlnMesnac.Model.dto;
using SlnMesnac.Model.enums;
using SlnMesnac.WPF.Page;
using Newtonsoft.Json.Linq;
using System.Collections;
using Microsoft.IdentityModel.Logging;
using System.Windows.Documents;
using SlnMesnac.Common;
using HslCommunication.Profinet.GE;
using static System.Net.Mime.MediaTypeNames;
using Application = System.Windows.Application;
using LiveCharts;
using System.Threading;
using SlnMesnac.Repository.service;
using LiveCharts.Defaults;
using static MaterialDesignThemes.Wpf.Theme.ToolBar;
using LiveCharts.Wpf;
using System.Windows.Media;
using System.Windows.Threading;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using SlnMesnac.Config;
namespace SlnMesnac.WPF.ViewModel
{
/// <summary>
/// 生产管理ViewModel
/// </summary>
public class ProdMgmtViewModel : ViewModelBase
{
private readonly ILogger<ProdMgmtViewModel> _logger;
private readonly ProdMgmtBusiness? _prodMgmtBusiness;
private readonly PalletStowBusiness? _palletStowBusiness;
private readonly IMesBaseBarcodeInfoService? _mesBaseBarcodeInfoService;
private readonly ProdCompletionBusiness? _prodCompletionBusiness;
private ObservableCollection<dynamic> listItems = new ObservableCollection<dynamic>();
#region 参数定义
#region 日产量柱状图X轴日期
/// <summary>
/// 日产量柱状图X轴日期
/// </summary>
private List<string> productionHourList = new List<string>();
public List<string> ProductionHourList
{
get { return productionHourList; }
set { productionHourList = value; }
}
#endregion
#region 型号统计柱状图
/// <summary>
/// 型号统计柱状图
/// </summary>
private SeriesCollection achievement = new SeriesCollection();
public SeriesCollection Achievement
{
get { return achievement; }
set { achievement = value; }
}
#endregion
/// <summary>
/// 工位名称
/// </summary>
private string stationName = string.Empty;
public string StationName
{
get { return stationName; }
set { stationName = value; RaisePropertyChanged(nameof(StationName)); }
}
/// <summary>
/// 订单编号
/// </summary>
private string orderCode = string.Empty;
public string OrderCode
{
get { return orderCode; }
set { orderCode = value; RaisePropertyChanged(nameof(OrderCode)); }
}
/// <summary>
/// 计划编号
/// </summary>
private string planCode = string.Empty;
public string PlanCode
{
get { return planCode; }
set { planCode = value; RaisePropertyChanged(nameof(PlanCode)); }
}
/// <summary>
/// 产品型号
/// </summary>
private string productModel = string.Empty;
public string ProductModel
{
get { return productModel; }
set { productModel = value; RaisePropertyChanged(nameof(ProductModel)); }
}
/// <summary>
/// 开始时间
/// </summary>
private string beginTime = string.Empty;
public string BeginTime
{
get { return beginTime; }
set { beginTime = value; RaisePropertyChanged(nameof(BeginTime)); }
}
/// <summary>
/// 计划数量
/// </summary>
private int planAmount = 0;
public int PlanAmount
{
get { return planAmount; }
set { planAmount = value; RaisePropertyChanged(nameof(planAmount)); }
}
/// <summary>
/// 完成数量
/// </summary>
public int complateAmout;
public int ComplateAmout
{
get { return complateAmout; }
set { complateAmout = value; RaisePropertyChanged(nameof(ComplateAmout)); }
}
/// <summary>
/// 差异值
/// </summary>
public int diffAmount;
public int DiffAmount
{
get { return diffAmount; }
set { diffAmount = value; RaisePropertyChanged(nameof(DiffAmount)); }
}
/// <summary>
/// 完成率
/// </summary>
public decimal compleRoution;
public decimal CompleRoution
{
get { return compleRoution; }
set { compleRoution = value; RaisePropertyChanged(nameof(CompleRoution)); }
}
/// <summary>
/// 计划列表DataGrid
/// </summary>
private ObservableCollection<MesProductPlanDto> planInfoDataGrid;
public ObservableCollection<MesProductPlanDto> PlanInfoDataGrid
{
get { return planInfoDataGrid; }
set { planInfoDataGrid = value; RaisePropertyChanged(() => PlanInfoDataGrid); }
}
/// <summary>
/// LisBox数据模板
/// </summary>
private IEnumerable logInfoListBox;
public IEnumerable LogInfoListBox
{
get { return logInfoListBox; }
set { logInfoListBox = value; RaisePropertyChanged(() => LogInfoListBox); }
}
#endregion
#region 事件定义
/// <summary>
/// 开始执行生产计划
/// </summary>
public RelayCommand<string> StartProdPlanCommand { get; set; }
/// <summary>
/// 暂停生产计划
/// </summary>
public RelayCommand<string> StopProdPlanCommand { get; set; }
#endregion
public ProdMgmtViewModel()
{
StartProdPlanCommand = new RelayCommand<string>(obj => StartProdPlan(obj));
StopProdPlanCommand = new RelayCommand<string>(obj => StopProdPlan(obj));
_logger = App.ServiceProvider.GetService<ILogger<ProdMgmtViewModel>>();
_prodMgmtBusiness = App.ServiceProvider.GetService<ProdMgmtBusiness>();
_palletStowBusiness = App.ServiceProvider.GetService<PalletStowBusiness>();
_prodCompletionBusiness = App.ServiceProvider.GetService<ProdCompletionBusiness>();
_mesBaseBarcodeInfoService = App.ServiceProvider.GetService<IMesBaseBarcodeInfoService>();
Task.Run(() =>
{
_prodMgmtBusiness.RefreshProdPlanListEvent += RefreshPlanDataGrid;
_prodMgmtBusiness.MatPutInValidEvent += MatPutInValidHandleEvent;
_prodMgmtBusiness.PrintMessageToListBoxEvent += PrintMessageToListBox;
_prodMgmtBusiness.InitProdPlan();
});
Task.Run(() =>
{
_prodCompletionBusiness.PrintMessageToListBoxEvent += PrintMessageToListBox;
// _prodCompletionBusiness.Init();
});
Init();
}
private void Init()
{
RefreChart();
DispatcherTimer _timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromMinutes(5);
_timer.Tick += Timer_Tick;
_timer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
RefreChart();
}
public void test()
{
// gunHelper.InstanceSerialPort();
// HttpHelper.JudgeAgvTaskComplete();
// HttpHelper.SendAgvTask("20245603");
//HttpHelper.JudgeAgvTaskComplete();
}
/// <summary>
/// 刷新计划执行
/// </summary>
/// <param name="prodPlan"></param>
private void RefreshPlanExec(MesProductPlanDto prodPlan)
{
if (prodPlan != null)
{
StationName = "磁悬";
OrderCode = prodPlan.OrderCode;
PlanCode = prodPlan.PlanCode;
ProductModel = prodPlan.MaterialName;
BeginTime = prodPlan.RealBeginTime.ToString("yyyy-MM-dd HH:mm:ss");
PlanAmount = Convert.ToInt32(prodPlan.PlanAmount);
ComplateAmout = Convert.ToInt32(prodPlan.CompleteAmount);
DiffAmount = Convert.ToInt32(prodPlan.PlanAmount) - Convert.ToInt32(prodPlan.CompleteAmount);
CompleRoution = Math.Round((prodPlan.CompleteAmount / prodPlan.PlanAmount) * 100, 2);
}
else
{
OrderCode = string.Empty;
PlanCode = string.Empty;
ProductModel = string.Empty;
BeginTime = string.Empty;
PlanAmount = 0;
ComplateAmout = 0;
DiffAmount = 0;
CompleRoution = 0;
}
}
/// <summary>
/// 刷新生产计划
/// </summary>
/// <param name="list"></param>
private async void RefreshPlanDataGrid(List<MesProductPlanDto> list)
{
try
{
await App.Current.Dispatcher.BeginInvoke((Action)(() =>
{
PlanInfoDataGrid = new ObservableCollection<MesProductPlanDto>();
if (list != null)
{
#region 按钮状态
// 假设初始状态所有计划的按钮状态
list.ForEach(plan =>
{
plan.StartEnable = true;
plan.StopEnable = false;
});
// 查找是否存在正在执行的计划
var executingPlan = list.FirstOrDefault(x => x.PlanStatus == PlanStatusEnum.);
if (executingPlan != null)
{
// 如果有正在执行的计划,只有该计划的暂停按钮可以点击,其他计划的按钮都不能点击
foreach (var plan in list)
{
if (plan == executingPlan)
{
plan.StopEnable = true; // 执行中的计划可以暂停
plan.StartEnable = false;
}
else
{
plan.StartEnable = false; // 其他计划不能开始
}
}
}
#endregion
list.OrderByDescending(x => x.PlanStatus);
list.ForEach(
arg =>
{
PlanInfoDataGrid.Add(arg);
});
var info = list.Where(x => x.PlanStatus == PlanStatusEnum.).ToList();
if (info.Count > 0)
{
RefreshPlanExec(info.First());
}
}
}));
}
catch (Exception ex)
{
_logger.LogError($"生产计划刷新异常:{ex.Message}");
}
}
/// <summary>
/// 开始生产计划事件
/// </summary>
/// <param name="obj"></param>
private void StartProdPlan(string obj)
{
try
{
//先检查是否有正在执行的计划
var hasPlan = planInfoDataGrid.Where(x => x.PlanStatus == PlanStatusEnum.).FirstOrDefault();
if (hasPlan != null)
{
var result = MessageBox.Show("有正在执行的计划,是否确认切换计划!", "确认", MessageBoxButton.YesNo);
if (result == MessageBoxResult.Yes)
{
hasPlan.PlanStatus = PlanStatusEnum.;
_prodMgmtBusiness.UpdateProdPlan(hasPlan);
}
else
{
return;
}
}
_logger.LogInformation($"开始执行{obj}计划");
var info = planInfoDataGrid.Where(x => x.PlanCode == obj).First();
if (info != null)
{
info.PlanStatus = PlanStatusEnum.;
info.PlanBeginTime = DateTime.Now;
}
_prodMgmtBusiness.UpdateProdPlan(info);
PrintMessageToListBox($"开始执行{obj}计划");
this.RefreshPlanExec(info);
}
catch (Exception e)
{
_logger.LogError($"开始事件处理异常:{e.Message}");
}
}
/// <summary>
/// 暂停生产计划事件
/// </summary>
/// <param name="obj"></param>
private void StopProdPlan(string obj)
{
try
{
_logger.LogInformation($"暂停执行{obj}计划");
var info = planInfoDataGrid.Where(x => x.PlanCode == obj).First();
if (info != null)
{
info.PlanStatus = PlanStatusEnum.;
//info.RealBeginTime = DateTime.Now;
}
PrintMessageToListBox($"暂停执行{obj}计划");
_prodMgmtBusiness.UpdateProdPlan(info);
this.RefreshPlanExec(null);
}
catch (Exception e)
{
_logger.LogError($"暂停事件处理异常:{e.Message}");
}
}
/// <summary>
/// 校验失败人工确认事件
/// </summary>
/// <param name="validType"></param>
/// <param name="productPlan"></param>
/// <param name="materialName"></param>
/// <param name="msg"></param>
/// <returns></returns>
private bool MatPutInValidHandleEvent(int validType, MesProductPlan productPlan, string materialName, string msg)
{
var result = false;
Application.Current.Dispatcher.Invoke(() =>
{
var alarmWindow = new SystemAlarmWindow();
var viewModel = new SystemAlarmViewModel();
viewModel.AlarmMsg = msg;
viewModel.AlarmConfirmed += (sender, isConfirmed) =>
{
result = isConfirmed;
alarmWindow.Close();
};
alarmWindow.DataContext = viewModel;
alarmWindow.ShowDialog();
});
return result;
}
/// <summary>
/// 系统运行日志输出
/// </summary>
/// <param name="message"></param>
private async void PrintMessageToListBox(string message)
{
await Task.Run(() =>
{
try
{
string formattedMessage = $"{DateTime.Now.ToString("HH:mm:ss.ss")} ==> {message}";
lock (listItems)
{
listItems.Add(formattedMessage);
while (listItems.Count > 120)
{
listItems.RemoveAt(0);
}
var orderedList = listItems.OrderByDescending(x => x).ToList(); // 排序后转为 List
Application.Current.Dispatcher.Invoke(() =>
{
LogInfoListBox = orderedList; // 更新 UI
});
}
}
catch (Exception ex)
{
_logger.LogError($"日志数据绑定异常:{ex.Message}");
}
});
}
/// <summary>
/// 刷新产量统计图表
/// </summary>
private async void RefreChart()
{
try
{
await Task.Run(() =>
{
ProductionHourList = new List<string>() { "8:00", "9:00", "10:00", "11:00", "12:00", "13:00", "14:00", "15:00", "16:00", "17:00", "18:00", "19:00" };
List<MesBaseBarcodeInfo> list = _mesBaseBarcodeInfoService.Query(x => x.bindTime != null && x.bindTime >= DateTime.Now.Date && x.bindTime <= DateTime.Now.AddDays(1)).ToList();
if (list != null && list.Count > 0)
{
Dictionary<string, int> hourProductionCount = new Dictionary<string, int>();
// 初始化字典每个小时的产量初始为0
foreach (var hour in ProductionHourList)
{
hourProductionCount[hour] = 0;
}
// 遍历查询结果,统计每个小时的产量
foreach (var item in list)
{
// 获取 bindTime 的小时部分
string hour = item.bindTime.Value.ToString("H:00");
// 如果小时在 ProductionHourList 中,则统计该小时的产量
if (hourProductionCount.ContainsKey(hour))
{
hourProductionCount[hour]++;
}
}
Application.Current.Dispatcher.Invoke(() =>
{
Achievement.Clear();
ChartValues<ObservablePoint> achievement = new ChartValues<ObservablePoint>();
int i = 0;
foreach (var kvp in hourProductionCount)
{
achievement.Add(new ObservablePoint(i++, kvp.Value));
}
//加一个汇总柱状图
ProductionHourList.Add("合计");
achievement.Add(new ObservablePoint(i, list.Count));
var column = new ColumnSeries();
column.DataLabels = true;
column.Title = "小时产量";
column.Values = achievement;
column.Foreground = Brushes.White;
Achievement.Add(column);
});
}
else
{
// ProductionHourList.Clear();
Achievement.Clear();
}
});
}catch(Exception ex)
{
_logger.LogError($"产量统计图表异常:{ex.Message}");
}
}
}
}