Files

581 lines
22 KiB
C#
Raw Permalink Normal View History

2026-09-07 08:07:08 +08:00
using JinYuan.Helper;
using JinYuan.Models;
using JinYuan.VirtualDataLibrary;
using Language;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Data;
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(0, (int)totalQty);//900
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); // (int)(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}");
try
{
DateTime time = DateTime.Now;
if (CommonMethods.strClass == "白班".Translated() || time.Hour >= 20)
{
int num = time.Subtract(Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 08:30:00"))).Hours;
num = num == 0 ? 1 : num;
if (ControlExtensions.MySQLDataDelete(ControlExtensions.DeleteAlarmCopyDateSql(num)) != null)
{
CommonMethods.AddLog(true, $@"已删除前{num}小时重复报警");
}
}
else if (time.Hour <= 8)
{
DateTime time2 = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd 08:30:00")).AddDays(-1);
int num1 = time.Subtract(time2).Hours;
num1 = num1 == 0 ? 1 : num1;
if (ControlExtensions.MySQLDataDelete(ControlExtensions.DeleteAlarmCopyDateSql(num1)) != null)
{
CommonMethods.AddLog(true, $@"已删除前{num1}小时重复报警");
}
}
}
catch (Exception ex1)
{
CommonMethods.AddLog(true, "删除重复报警异常".Translated() + $":{ex1.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();
}
#region 删除MySQL数据库中数据
/// <summary>
/// 删除MySQL数据库中数据
/// </summary>
/// <param name="strSql"></param>
/// <returns>true:存在</returns>
public static object MySQLDataDelete(string strSql)//CommonMethods.m_DBCtrl.DeleteAlarmCopyDateSql)
{
object result = null;
try
{
string strMySQLConnectString = "Server=localhost;" +
"DataBase=LargeSquareOne;" +
"User Id=root;" +
"Password=eve123456;" +
"Persist Security Info=true;" +
"Allow Zero Datetime=true;" +
"Character Set=utf8;" +
"Pooling=true;" +
"Min Pool Size=5;" +
"Max Pool Size=50;" +
"Connection Timeout=60;" +
"Command Timeout=300;" +
"Allow User Variables=true;";
using (MySqlConnection connection = new MySqlConnection(strMySQLConnectString))
{
using (MySqlCommand cmd = new MySqlCommand(strSql, connection))
{
cmd.CommandTimeout = 3;//默认30s
if (connection.State == ConnectionState.Closed)
{
connection.Open();
}
cmd.CommandTimeout = 3;
result = cmd.ExecuteNonQuery();
}
}
if (result != null)
{
return (int)result;
}
else
{
return null;
}
}
catch (Exception e)
{
return null;
}
}
/// <summary>
/// 删除报警表重复数据
/// </summary>
/// <param name="time"></param>
/// <returns></returns>
public static string DeleteAlarmCopyDateSql(int time)
{
string strSql = $@"DELETE t1
FROM
`alarmcountentry` t1
LEFT JOIN (
SELECT MIN(id) as min_id
FROM `alarmcountentry`
WHERE `alarmtime` >= DATE_SUB(NOW(), INTERVAL {time} HOUR)
GROUP BY `plcadress`, `alarmcontent`
) t2 ON t1.id = t2.min_id
WHERE
t1.alarmtime >= DATE_SUB(NOW(), INTERVAL {time} HOUR)
AND t2.min_id IS NULL;";
return strSql;
}
#endregion
}
}