Files
2026-09-09 18:42:38 +08:00

473 lines
18 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using JinYuan.Helper;
using JinYuan.Models;
using JinYuan.VirtualDataLibrary;
using Language;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Text;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
namespace LargeSquareOne
{
public partial class FrmMonitor : MultiLanguageForm
{
private static readonly object uiLock = new object();
private static FrmMonitor _instance;
private readonly CancellationTokenSource _cts = new CancellationTokenSource();
private readonly PrivateFontCollection _font = new PrivateFontCollection();
private Font _myFont;
public static FrmMonitor Instance
{
get
{
lock (uiLock)
{
return _instance ??= new FrmMonitor();
}
}
}
public FrmMonitor()
{
InitializeComponent();
InitializeFormSettings();
//LoadCustomFont();
this.FormClosing += FrmMonitor_FormClosing;
}
private void InitializeFormSettings()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.DoubleBuffer |
ControlStyles.ResizeRedraw |
ControlStyles.Selectable |
ControlStyles.SupportsTransparentBackColor, true);
}
private void LoadCustomFont()
{
try
{
var fontPath = Path.Combine(Environment.CurrentDirectory, "Assts", "Fonts", "FZY4JW.ttf");
_font.AddFontFile(fontPath);
var myFontFamily = new FontFamily(_font.Families[0].Name, _font);
_myFont = new Font(myFontFamily, 20, FontStyle.Bold);
}
catch (Exception ex)
{
CommonMethods.AddLog(true, "加载字体异常".Translated() + $":{ex.Message}");
}
}
private void FrmMonitor_FormClosing(object sender, FormClosingEventArgs e)
{
_cts.Cancel();
_font?.Dispose();
_myFont?.Dispose();
}
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0014) return; // 禁掉清除背景消息
base.WndProc(ref m);
}
private async void FrmMonitor_Load(object sender, EventArgs e)
{
try
{
SetChart();
await RefreshAllDataAsync();
await StartPeriodicRefreshAsync(_cts.Token);
}
catch (Exception ex)
{
CommonMethods.AddLog(true, "窗体加载异常".Translated() + $":{ex.Message}");
}
}
private void SetChart()
{
try
{
#region 24小时统计
Chart12HourTotal.Series.Clear();
Chart12HourTotal.ChartAreas[0].AxisY.Minimum = 0;
Chart12HourTotal.ChartAreas[0].AxisY.Maximum = 2000;
ChartHelper.AddSeries(Chart12HourTotal, "投入".Translated(), SeriesChartType.Column,
ChartValueType.Auto, MarkerStyle.Diamond, 8, Color.DarkTurquoise,
Color.Aqua, "", false, true);
ChartHelper.AddSeries(Chart12HourTotal, "产出".Translated(), SeriesChartType.Column,
ChartValueType.Auto, MarkerStyle.Diamond, 8, Color.PaleGoldenrod,
Color.PaleGoldenrod, "", false, true);
ChartHelper.AddSeries(Chart12HourTotal, "优率".Translated(), SeriesChartType.Spline,
ChartValueType.String, MarkerStyle.Circle, 8, Color.Lime,
Color.Lime, "#VAL{P}", true, true);
ChartHelper.SetStyle(Chart12HourTotal, Color.Transparent, Color.White);
ChartHelper.SetLegend(Chart12HourTotal, Docking.Left, StringAlignment.Center,
Color.Transparent, Color.White);
ChartHelper.SetXY(Chart12HourTotal, "时间".Translated(), "数值".Translated(), -45, StringAlignment.Center,
Color.White, Color.White, AxisArrowStyle.None, 1, true);
ChartHelper.SetMajorGrid(Chart12HourTotal, Color.Transparent, 20, 2);
#endregion
}
catch (Exception ex)
{
CommonMethods.AddLog(true, "图表初始化异常".Translated() + $":{ex.Message}");
}
}
private async Task StartPeriodicRefreshAsync(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
try
{
await RefreshAllDataAsync();
await Task.Delay(2000, ct);
}
catch (OperationCanceledException)
{
break;
}
catch (Exception ex)
{
CommonMethods.AddLog(true, "定时刷新异常".Translated() + $":{ex.Message}");
await Task.Delay(1000, ct);
}
}
}
private async Task RefreshAllDataAsync()
{
var tasks = new[]
{
Refish12ProdQtyAsync(),
RefreshXiaoLvDataAsync(),
RefreshChatTop10AlarmDataAsync(),
RefreshChatNGDataAsync()
};
await Task.WhenAll(tasks);
}
private async Task Refish12ProdQtyAsync()
{
await Task.Run(() =>
{
if (IsDisposed) return;
this.InvokeIfRequired(() =>
{
var data = CommonMethods.Lst_Prod12HourData; // CommonMethods.Lst_Prod12HourData?.Count > 0 ? CommonMethods.Lst_Prod12HourData : MockDataGenerator.Generate12HourData();
UpdateChart12HourData(data);
});
});
}
private void UpdateChart12HourData(List<Chart12HourData> data)
{
try
{
var maxValue = data.Max(x => x.ProdIn);
Chart12HourTotal.ChartAreas[0].AxisY.Minimum = 0;
Chart12HourTotal.ChartAreas[0].AxisY.Maximum = (int)maxValue + 1500;
// 直接使用数据,不需要额外排序
var x1 = data.Select(c => c.DisplayTime).ToList();
var y1 = data.Select(c => c.ProdIn).ToList();
var y2 = data.Select(c => c.ProdOut).ToList();
var y3 = data.Select(c => c.OKRatio).ToList();
Chart12HourTotal.Series[0].Points.DataBindXY(x1, y1);
Chart12HourTotal.Series[1].Points.DataBindXY(x1, y2);
Chart12HourTotal.Series[2].Points.DataBindXY(x1, y3);
// 设置X轴标签的角度,提高可读性
Chart12HourTotal.ChartAreas[0].AxisX.LabelStyle.Angle = 0;
// 确保显示所有标签
Chart12HourTotal.ChartAreas[0].AxisX.Interval = 1;
}
catch (Exception ex)
{
CommonMethods.AddLog(true, "更新12小时数据异常".Translated() + $":{ex.Message}");
}
}
// 效率数据也可以添加模拟数据
private async Task RefreshXiaoLvDataAsync()
{
await Task.Run(() =>
{
if (IsDisposed) return;
// 使用实际数据或模拟数据
var utilizationRate = Convert.ToDouble(CommonMethods.JiaDL) * 100; // CommonMethods.JiaDL >= 0
//? Convert.ToDouble(CommonMethods.JiaDL) * 100
//: MockDataGenerator._random.Next(60, 95);
var totalQty = CommonMethods.TotalQty;
//CommonMethods.TotalQty >= 0
// ? CommonMethods.TotalQty
// : MockDataGenerator._random.Next(1000, 5000);
var okQty = CommonMethods.ProOKQty;
//CommonMethods.ProOKQty >= 0
// ? CommonMethods.ProOKQty
// : MockDataGenerator._random.Next(900, (int)totalQty);
var yieldRate = totalQty == 0 ? 0 :
Convert.ToDouble((Convert.ToDouble(okQty) /
Convert.ToDouble(totalQty) * 100.0)
.ToString("f2"));
this.InvokeIfRequired(() =>
{
UpdateEfficiencyControls(utilizationRate, yieldRate, (int)totalQty, (int)okQty);
UpdateTimeDisplay();
UpdateEnergyDisplay();
});
});
}
private double CalculateYieldRate()
{
if (CommonMethods.TotalQty == 0) return 0;
return Convert.ToDouble((Convert.ToDouble(CommonMethods.ProOKQty) /
Convert.ToDouble(CommonMethods.TotalQty) * 100.0)
.ToString("f2"));
}
private void UpdateEfficiencyControls(double utilizationRate, double yieldRate, int totalQty, int okQty)
{
try
{
titleModeName.Title = CommonMethods.mesConfig.ModelName ?? "测试型号";
titleFactory_code.Title = CommonMethods.mesConfig.siteCode ?? "TEST001";
titleLine_No.Title = CommonMethods.mesConfig.lineCode ?? "LINE01";
titleEqp_code.Title = CommonMethods.mesConfig.equipNum ?? "EQP001";
proUtilizationRate.FloatValue = (float)utilizationRate;
proPPM.IntValue = (int)CommonMethods.Ppm; // (CommonMethods.Ppm > 0 ? CommonMethods.Ppm : MockDataGenerator._random.Next(100, 1000));
proOKQty.IntValue = okQty;
proOKRatio.Value = yieldRate;
proTotalQty.TotalValue = totalQty;
}
catch (Exception ex)
{
CommonMethods.AddLog(true, "更新效率控件异常".Translated() + $":{ex.Message}");
}
}
private void UpdateTimeDisplay()
{
try
{
if (CommonMethods.PlcOpenAndRunTime?.Count > 0)
{
titleStartTime.Title = $"{CommonMethods.PlcOpenAndRunTime[0]}:" +
$"{CommonMethods.PlcOpenAndRunTime[1]}:" +
$"{CommonMethods.PlcOpenAndRunTime[2]}";
titleRunTime.Title = $"{CommonMethods.PlcOpenAndRunTime[3]}:" +
$"{CommonMethods.PlcOpenAndRunTime[4]}:" +
$"{CommonMethods.PlcOpenAndRunTime[5]}";
}
}
catch (Exception ex)
{
CommonMethods.AddLog(true, "更新时间显示异常".Translated() + $":{ex.Message}");
}
}
private void UpdateEnergyDisplay()
{
try
{
if (CommonMethods.listElectricEnergy?.Count > 0)
{
EyMaterH1.ElectricEnergy = CommonMethods.listElectricEnergy[0];
}
}
catch (Exception ex)
{
CommonMethods.AddLog(true, "更新能源显示异常".Translated() + $":{ex.Message}");
}
}
private async Task RefreshChatTop10AlarmDataAsync()
{
await Task.Run(() =>
{
if (IsDisposed) return;
this.InvokeIfRequired(() =>
{
UpdateAlarmChart();
});
});
}
private void UpdateAlarmChart()
{
try
{
var alarmData = CommonMethods.Lst_AlarmTop10_Qty;
// CommonMethods.Lst_AlarmTop10_Qty?.Count > 0
//? CommonMethods.Lst_AlarmTop10_Qty
//: MockDataGenerator.GenerateAlarmTop10Data();
if (alarmData?.Count > 0)
{
chartAlarmData.Series.Clear();
chartAlarmData.Titles.Clear();
var maxValue = alarmData.Max(x => x.DataCount);
chartAlarmData.ChartAreas[0].AxisY.Minimum = 0;
chartAlarmData.ChartAreas[0].AxisY.Maximum = (int)maxValue + 20;
foreach (var item in alarmData)
{
ChartHelper.AddSeries(chartAlarmData, item.DataType,
SeriesChartType.Column, ChartValueType.Auto,
MarkerStyle.Diamond, 4, Color.DarkTurquoise,
Color.White, "", false, true);
}
ConfigureAlarmChart();
var xData = alarmData.Select(c => c.DataType).ToList();
var yData = alarmData.Select(c => c.DataCount).ToList();
chartAlarmData.Series[0].Points.DataBindXY(xData, yData);
}
}
catch (Exception ex)
{
CommonMethods.AddLog(true, "更新报警图表异常".Translated() + $":{ex.Message}");
}
}
private void ConfigureAlarmChart()
{
ChartHelper.SetTitle(chartAlarmData, "报警TOP10".Translated(),
new Font("微软雅黑", 12), Docking.Top, Color.White);
ChartHelper.SetStyle(chartAlarmData, Color.Transparent, Color.White);
ChartHelper.SetLegend(chartAlarmData, Docking.Top,
StringAlignment.Center, Color.Transparent, Color.White);
ChartHelper.SetXY(chartAlarmData, "报警项".Translated(), "次数".Translated(), -45,
StringAlignment.Center, Color.White, Color.White,
AxisArrowStyle.None, 1, false);
ChartHelper.SetMajorGrid(chartAlarmData, Color.Transparent, 20, 2);
}
private void BindAlarmChartData()
{
var xData = CommonMethods.Lst_AlarmTop10_Qty.Select(c => c.DataType).ToList();
var yData = CommonMethods.Lst_AlarmTop10_Qty.Select(c => c.DataCount).ToList();
chartAlarmData.Series[0].Points.DataBindXY(xData, yData);
}
private async Task RefreshChatNGDataAsync()
{
await Task.Run(() =>
{
if (IsDisposed) return;
this.InvokeIfRequired(() =>
{
UpdateNGChart();
});
});
}
private void UpdateNGChart()
{
try
{
var ngData = CommonMethods.Lst_DefectTypeQty;
//CommonMethods.Lst_DefectTypeQty?.Count > 0
// ? CommonMethods.Lst_DefectTypeQty
// : MockDataGenerator.GenerateNGData();
if (ngData?.Count > 0)
{
chartNgShow.Series.Clear();
chartNgShow.Titles.Clear();
var maxValue = ngData.Max(x => x.DataCount);
chartNgShow.ChartAreas[0].AxisY.Minimum = 0;
chartNgShow.ChartAreas[0].AxisY.Maximum = (int)maxValue + 100;
foreach (var item in ngData)
{
ChartHelper.AddSeries(chartNgShow, item.DataType,
SeriesChartType.Column, ChartValueType.Auto,
MarkerStyle.Diamond, 4, Color.Red,
Color.White, "", false, true);
}
ConfigureNGChart();
var xData = ngData.Select(c => c.DataType).ToList();
var yData = ngData.Select(c => c.DataCount).ToList();
chartNgShow.Series[0].Points.DataBindXY(xData, yData);
}
}
catch (Exception ex)
{
CommonMethods.AddLog(true, "更新不良图表异常".Translated() + $":{ex.Message}");
}
}
private void ConfigureNGChart()
{
ChartHelper.SetTitle(chartNgShow, "各不良项".Translated(),
new Font("微软雅黑", 12), Docking.Top, Color.White);
ChartHelper.SetStyle(chartNgShow, Color.Transparent, Color.White);
ChartHelper.SetLegend(chartNgShow, Docking.Top,
StringAlignment.Center, Color.Transparent, Color.White);
ChartHelper.SetXY(chartNgShow, "项名".Translated(), "数值".Translated(), 0,
StringAlignment.Center, Color.White, Color.White,
AxisArrowStyle.None, 1, false);
ChartHelper.SetMajorGrid(chartNgShow, Color.Transparent, 1, 1);
}
private void BindNGChartData()
{
var xData = CommonMethods.Lst_DefectTypeQty.Select(c => c.DataType).ToList();
var yData = CommonMethods.Lst_DefectTypeQty.Select(c => c.DataCount).ToList();
chartNgShow.Series[0].Points.DataBindXY(xData, yData);
}
}
// 扩展方法
public static class ControlExtensions
{
public static void InvokeIfRequired(this Control control, Action action)
{
if (control.IsDisposed) return;
if (control.InvokeRequired)
control.BeginInvoke(action);
else
action();
}
}
}