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.

565 lines
19 KiB
C#

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 void RefreshPlanDataGrid(List<MesProductPlanDto> list)
{
try
{
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", "20: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}");
}
}
}
}