Files
1258/LargeSquareOne/FrmMain.cs
T

2003 lines
81 KiB
C#
Raw Normal View History

2026-08-04 18:36:40 +08:00
using AntdUI;
using HML;
using JinYuan.ControlCenters;
using JinYuan.ControlLib;
using JinYuan.ControlLib.Models;
using JinYuan.Helper;
using JinYuan.MES.Models;
using JinYuan.Models;
using JinYuan.VirtualDataLibrary;
using Language;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Text;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace LargeSquareOne
{
public partial class FrmMain : MultiLanguageForm
{
// 窗体实例缓存
private readonly Dictionary<FormNames, Form> _formCache = new Dictionary<FormNames, Form>();
private ControlCenter _controlCenter;
//实时更新的定时器
private System.Timers.Timer updateTimer;
//定时存储定时器
private System.Timers.Timer storeTimer;
private DateTime _lastStoreTick = DateTime.MinValue;
private readonly TimeSpan _minStoreInterval = TimeSpan.FromMilliseconds(1000);
private DateTime _lastFullUpdate = DateTime.MinValue;
private string _cachedAlarmText = "";
private DateTime _lastScrollUpdate = DateTime.MinValue;
private readonly TimeSpan _scrollUpdateInterval = TimeSpan.FromMilliseconds(100);
//加载字体
private PrivateFontCollection font = new PrivateFontCollection();
/// <summary>
/// 时间更新委托
/// </summary>
/// <param name="time"></param>
public delegate void ShowTimeHandler(DateTime time);
//当前页面索引
private int CurrentIndex = 0;
private List<NaviButton2> naviButton2s = new List<NaviButton2>();
public bool IsNoOrg = false;
public bool IsSetParam = false;
private readonly object _statusLock = new object();
private DateTime _lastSafeInvoke = DateTime.MinValue;
// 添加一个上次更新电池状态的时间记录
private DateTime _lastBatteryStatusUpdate = DateTime.MinValue;
private readonly TimeSpan _batteryUpdateInterval = TimeSpan.FromMilliseconds(200); // 限制每 200ms 更新一次电池 UI
// 下拉框数据缓存(核心优化:避免频繁绑定)
private List<DropDownListPlusItem> _cachedModelItems = new List<DropDownListPlusItem>();
// 委托队列(核心优化:防委托堆积)
private List<IAsyncResult> _pendingInvokes = new List<IAsyncResult>();
// MES状态缓存(核心优化:降低更新频率)
private DateTime _lastMESUpdate = DateTime.MinValue;
private bool _lastMESValue = false;
public FrmMain()
{
InitializeComponent();
// 添加应用程序域异常处理
AppDomain.CurrentDomain.FirstChanceException += (sender, e) =>
{
if (e.Exception is System.InvalidOperationException)
{
Debug.WriteLine($"[全局异常] InvalidOperationException: {e.Exception.Message}");
Debug.WriteLine($"[堆栈] {e.Exception.StackTrace}");
// 检查是否是跨线程异常
if (e.Exception.StackTrace.Contains("System.Windows.Forms.Control"))
{
Debug.WriteLine("[诊断] 这是跨线程访问UI控件的异常!");
}
}
};
Application.AddMessageFilter(new InputMessageFilter(() =>
{
lastActivityTime = DateTime.Now;
}));
2026-08-04 18:36:40 +08:00
// 双缓冲全覆盖
this.DoubleBuffered = true;
InitializeOptimizedControlStyles();
InitializeLanguageSwitch();
SetCombOrg();
IsNoOrg = true;
this.Resize += FrmNewMain_Resize; // 关联 Resize 事件
#region 添加工具栏
naviButton2s.AddRange(new[]
{
nav_Monitor, nav_DataMonitor, nav_CPK, nav_BatteryStatus, nav_QRCode,
nav_AlarmLog, nav_HistotryData, nav_SetSystem, nav_System, nav_UserInfo
});
#endregion
InitializeTimersOptimized();
CommonMethods.listener.Start();
//刷卡模式
if (CommonMethods.sysConfig.SwipeCardMode)
{
CommonMethods.listener.ScanerEvent += Listener_ScanerEvent;
}
}
// 控件样式初始化提取
private void InitializeOptimizedControlStyles()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.ResizeRedraw | ControlStyles.Selectable |
ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
this.UpdateStyles();
// 容器控件启用双缓冲
SetControlDoubleBuffer(MainPanel, true);
SetControlDoubleBuffer(TopPanel, true);
}
// 通用双缓冲设置方法
private void SetControlDoubleBuffer(Control ctrl, bool enable)
{
// 空值校验,避免空引用异常
if (ctrl == null) return;
try
{
// 1. 设置 DoubleBuffered 私有属性
PropertyInfo doubleBufferedProp = ctrl.GetType().GetProperty(
"DoubleBuffered",
BindingFlags.Instance | BindingFlags.NonPublic);
doubleBufferedProp?.SetValue(ctrl, enable, null);
// 2. 反射调用 SetStyle 受保护方法
MethodInfo setStyleMethod = typeof(Control).GetMethod(
"SetStyle",
BindingFlags.Instance | BindingFlags.NonPublic,
null,
new[] { typeof(ControlStyles), typeof(bool) },
null);
setStyleMethod?.Invoke(ctrl, new object[]
{
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.UserPaint,
enable
});
// 3. 反射调用 UpdateStyles 受保护方法
MethodInfo updateStylesMethod = typeof(Control).GetMethod(
"UpdateStyles",
BindingFlags.Instance | BindingFlags.NonPublic);
updateStylesMethod?.Invoke(ctrl, null);
}
catch (Exception ex)
{
// 捕获反射调用可能出现的异常
MessageBox.Show($"设置双缓冲失败:{ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private DateTime lastActivityTime;
private System.Windows.Forms.Timer idleTimer;
2026-08-04 18:36:40 +08:00
// 定时器初始化优化
private void InitializeTimersOptimized()
{
// 实时更新定时器(1秒)
updateTimer = new System.Timers.Timer(1000);
updateTimer.Elapsed += UpdateTimer_Tick;
updateTimer.AutoReset = true;
updateTimer.Start();
// 定时存储定时器(1秒)
storeTimer = new System.Timers.Timer(1000);
storeTimer.Elapsed += StoreTimer_Elapsed;
storeTimer.AutoReset = true;
storeTimer.Start();
// 定时退出当前用户
idleTimer = new System.Windows.Forms.Timer();
idleTimer.Interval = 1000;
idleTimer.Tick += (s, e) =>
{
if ((DateTime.Now - lastActivityTime).TotalMinutes >= 1)
{
idleTimer.Stop();
// 处理用户超时
this.BeginInvoke(new Action(() => LoginLocalOut()));
}
};
idleTimer.Start();
2026-08-04 18:36:40 +08:00
}
private async void FrmNewMain_Load(object sender, EventArgs e)
{
InitReadInI();
UserTimeOut(30);
_controlCenter = ControlCenter.Instance;
//await ControlCenter.Instance.StartAsync().ConfigureAwait(false);
await ControlCenter.Instance.StartAsync();
// 回到UI线程更新用户信息
this.BeginInvoke(new Action(() =>
{
// 1.设置登录用户
this.lbl_LoginLevel.Text = CommonMethods.currentAdmin?.LoginLevel;
this.lbl_LoginName.Text = CommonMethods.currentAdmin?.LoginName;
// 2.打开初始窗体
CommonNaviButton_Click(this.nav_AlarmLog, null);
CommonNaviButton_Click(this.nav_Monitor, null);
CommonNaviButton_Click(this.nav_DataMonitor, null);
CommonNaviButton_Click(this.nav_QRCode, null);
2026-08-31 14:58:12 +08:00
//CommonNaviButton_Click(this.nav_BatteryStatus, null);
2026-08-04 18:36:40 +08:00
// 登录日志
CommonMethods.AddOPLog(false, "登录成功,登录用户".Translated() + $":{CommonMethods.currentAdmin?.LoginName}," + "权限".Translated() + $":{CommonMethods.currentAdmin?.LoginLevel}");
}));
if (CommonMethods.sysConfig != null)
{
CommonMethods.AddLog(false, "加载系统配置成功".Translated());
}
else
{
CommonMethods.AddLog(true, "加载系统配置失败".Translated());
}
// 自动锁屏
if (CommonMethods.sysConfig.AutoLock)
{
Application.AddMessageFilter(new MessageFilter());
}
CheckMesLogin();
storeTimer.Enabled = true;
updateTimer.Enabled = true;
this.BeginInvoke(new MethodInvoker(() =>
{
AdjustUCRollTextFrequency();
}));
}
private void AdjustUCRollTextFrequency()
{
try
{
// 使用反射查找UCRollText的Timer并调整频率
var timerField = ucRollText1.GetType().GetField("_scrollTimer",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (timerField != null)
{
var timer = timerField.GetValue(ucRollText1) as System.Windows.Forms.Timer;
if (timer != null)
{
timer.Interval = 80;
Debug.WriteLine($"UCRollText频率已调整为: {timer.Interval}ms");
}
}
}
catch (Exception ex)
{
Debug.WriteLine($"调整UCRollText频率失败: {ex.Message}");
}
}
private void CheckMesLogin()
{
if (CommonMethods.sysConfig.MesModeSwitching && !CommonMethods.mesConfig.IsLoginMesOK)
{
new FrmMsgBoxOutWithAck(2, "当前为MES模式,请登录!".Translated(), "MES未登录".Translated()).ShowDialog();
using (var frmLoginMes = new FrmLoginMes())
{
frmLoginMes.ShowDialog();
}
}
}
#region PLC后台读取任务
/// <summary>
/// PLC后台读取专用任务(独立线程,不阻塞UI和其他操作)
/// </summary>
//private async Task PLCBackgroundReadTask()
//{
// while (!_cts.Token.IsCancellationRequested)
// {
// try
// {
// // 信号量确保同一时间只有一个PLC读取操作
// await _plcSemaphore.WaitAsync(_cts.Token).ConfigureAwait(false);
// if (CommonMethods.IsRun && CommonMethods.plcDevices != null && CommonMethods.plcDevices.Count > 0)
// {
// // 异步读取PLC数据,超时控制(避免卡死)
// var plcDevice = CommonMethods.plcDevices[0];
// await WaitWithTimeout(
// Task.Run(() =>
// {
// // PLC数据读取逻辑
// // plcDevice.ReadAllData();
// }, _cts.Token),
// TimeSpan.FromMilliseconds(500)
// ).ConfigureAwait(false);
// }
// }
// catch (OperationCanceledException)
// {
// // 任务取消,正常退出
// break;
// }
// catch (TimeoutException)
// {
// LogHelper.Instance.WriteLog("PLC读取超时,跳过本次读取");
// }
// catch (Exception ex)
// {
// LogHelper.Instance.WriteEX("PLC后台读取异常", ex);
// }
// finally
// {
// _plcSemaphore.Release();
// }
// // 控制PLC读取频率(50ms一次,可根据需要调整)
// await Task.Delay(50, _cts.Token).ConfigureAwait(false);
// }
//}
#endregion
#region 读取配置文件
/// <summary>
/// 读取配置文件
/// </summary>
public void InitReadInI()
{
#region 系统配置
CommonMethods.sysConfig = CommonMethods.GetSysConfig();
#endregion
#region MES配置
CommonMethods.mesConfig.RotueServerIP = CommonMethods.GetConfigValue(CommonMethods.Configxml, "MES_CONFIG", "StorageServerIP", "192.168.2.108");
///获取MES参数
CommonMethods.mesConfig = CommonMethods.GetMesConfig();
CommonMethods.LoadFDConfig();
CommonMethods.LoadFDConfigMappings();
//CommonMethods.btwConfig = CommonMethods.GetBtwConfig();
CommonMethods.mesConfig.electricMeterNum.Clear();
string str = CommonMethods.GetConfigValue(CommonMethods.Configxml, "MES_CONFIG", "SmartMeterCode", "1");
if (str.Contains(','))
{
CommonMethods.mesConfig.electricMeterNum.AddRange(str.Split(','));
}
CommonMethods.ChangeClassTime = CommonMethods.GetConfigValue(CommonMethods.Configxml, "MES_CONFIG", "ShiftChangeTime", "20:30:00");
string rootLogPath = CommonMethods.GetConfigValue(CommonMethods.Configxml, "MES_CONFIG", "MESLogPath", "D:\\APILog");
CommonMethods.strDeletepath = rootLogPath;
CommonMethods.strAlarmLogspath = Path.Combine(rootLogPath, "Logs", "AlarmLogs");
CommonMethods.strMesLogspath = Path.Combine(rootLogPath, "Logs", "MesLogs");
CommonMethods.strSystemLogspath = Path.Combine(rootLogPath, "Logs", "SystemLogs");
CommonMethods.strErrorLogspath = Path.Combine(rootLogPath, "Logs", "ErrorLogs");
CommonMethods.strsqlLogspath = Path.Combine(rootLogPath, "Logs", "SqlLogs");
CommonMethods.strWattrMeterpath = Path.Combine(rootLogPath, "Logs", "智能电表数据");
#endregion
CommonMethods.mesConfig.listAntiDustAirSpeedNum.Clear();
CommonMethods.mesConfig.AntiDustAirSpeedCount = Convert.ToInt32(CommonMethods.GetConfigValue(CommonMethods.Configxml, "ANEMOMETER", "AntiDustAirSpeedCount", "1"));
for (int i = 0; i < CommonMethods.mesConfig.AntiDustAirSpeedCount; i++)
{
CommonMethods.mesConfig.listAntiDustAirSpeedNum.Add(CommonMethods.GetConfigValue(CommonMethods.Configxml, "ANEMOMETER", $"AntiDustAirSpeed{i + 1}", "0"));
}
}
#endregion
#region 无操作 系统锁屏+切换到主监控界面
private async void UpdateTimer_Tick(object sender, EventArgs e)
{
Debug.WriteLine($"[UpdateTimer] {DateTime.Now:HH:mm:ss.fff} - 开始执行");
try
{
// 只处理锁屏和界面切换检查
if (CommonMethods.sysConfig.AutoLock)
{
CommonMethods.tickCount++;
int threshold = CommonMethods.sysConfig.LockPeriod * 60;
if (CommonMethods.tickCount >= threshold)
{
CommonMethods.tickCount = 0;
this.BeginInvoke(new Action(() => LockWorkStation()));
}
}
if (CommonMethods.sysConfig.AutoQieHuanM)
{
CommonMethods.tickHomeCount++;
int homeThreshold = CommonMethods.sysConfig.QieHuanMPeriod * 60;
if (CommonMethods.tickHomeCount >= homeThreshold)
{
CommonMethods.tickHomeCount = 0;
this.BeginInvoke((Action)(() =>
CommonNaviButton_Click(this.nav_Monitor, null)));
}
}
}
catch (Exception ex)
{
Debug.WriteLine($"UpdateTimer异常: {ex.Message}");
}
Debug.WriteLine($"[UpdateTimer] {DateTime.Now:HH:mm:ss.fff} - 结束执行");
}
private void StoreTimer_Elapsed(object sender, EventArgs e)
{
Debug.WriteLine($"[StoreTimer] {DateTime.Now:HH:mm:ss.fff} - 开始执行");
try
{
// 防抖:800ms 内只执行一次
if (DateTime.Now - _lastSafeInvoke < TimeSpan.FromMilliseconds(800))
return;
_lastSafeInvoke = DateTime.Now;
// UI 操作必须封送回主线程
if (this.IsHandleCreated || !this.IsDisposed)
{
this.BeginInvoke((Action)(() =>
ShowButtonEven_Run(DateTime.Now)));
}
}
catch { }
Debug.WriteLine($"[StoreTimer] {DateTime.Now:HH:mm:ss.fff} - 结束执行");
//// 1. 异步执行,避免阻塞定时器线程
//Task.Run(() =>
//{
// // 2. 防抖:800ms内只执行一次,避免高频更新
// if (DateTime.Now - _lastSafeInvoke < TimeSpan.FromMilliseconds(800))
// return;
// lock (_statusLock)
// {
// _lastSafeInvoke = DateTime.Now;
// // 3. 安全更新UI:通过BeginInvoke,且只更新变化的数据
// SafeInvoke(() => ShowButtonEven_Run(DateTime.Now));
// }
//});
//Debug.WriteLine($"[StoreTimer] {DateTime.Now:HH:mm:ss.fff} - 结束执行");
}
[DllImport("user32", SetLastError = true)]
public static extern bool LockWorkStation();
#endregion
/// <summary>
/// 刷卡事件
/// </summary>
/// <param name="codes"></param>
private void Listener_ScanerEvent(ScanerHook.ScanerCodes codes)
{
// 非UI线程,必须切UI上下文
//if (this.InvokeRequired)
//{
// this.Invoke(new Action<void>(Listener_ScanerEvent), codes);
// return;
//}
if (string.IsNullOrWhiteSpace(codes.Result))
{
//AntdUI.Message.Warn(this, "读取卡片为空,请重新刷卡");
new FrmMsgBoxOutWithAck(3, "读取卡片为空,请重新刷卡".Translated(), "登录提示".Translated()).ShowDialog();
return;
}
//调用查询方法
var sysAdmin = CommonMethods.db.Query<SysAdmin>(it => it.LoginUid == codes.Result);
if (sysAdmin == null)
{
new FrmMsgBoxOutWithAck(3, "登录用户或密码错误".Translated(), "登录提示".Translated()).ShowDialog();
return;
}
CommonMethods.IsLoginOk = true;
//存储用户对象
CommonMethods.currentAdmin = sysAdmin;
//1.设置登录用户
this.lbl_LoginLevel.Text = CommonMethods.currentAdmin?.LoginLevel;
this.lbl_LoginName.Text = CommonMethods.currentAdmin?.LoginName;
//登录日志
CommonMethods.AddOPLog(false, "登录成功,登录用户".Translated() + $":{CommonMethods.currentAdmin?.LoginName}," + "权限".Translated() + $":{CommonMethods.currentAdmin?.LoginLevel}");
}
#region 获取日期/星期,班次信息,更新
private int _showButtonRunCount = 0;
private DateTime _lastDebugOutput = DateTime.Now;
private void ShowButtonEven_Run(DateTime time)
{
Debug.WriteLine($"ShowButtonEven_Run on Thread: {System.Threading.Thread.CurrentThread.ManagedThreadId}");
_showButtonRunCount++;
// 确保至少间隔800ms
if (DateTime.Now - _lastDebugOutput < TimeSpan.FromMilliseconds(800))
return;
// 每5次输出一次调试信息
if (_showButtonRunCount % 5 == 0 && DateTime.Now - _lastDebugOutput > TimeSpan.FromSeconds(2))
{
Debug.WriteLine($"[ShowButtonEven_Run] 第{_showButtonRunCount}次执行,间隔: {(DateTime.Now - _lastDebugOutput).TotalMilliseconds:F0}ms");
_lastDebugOutput = DateTime.Now;
}
lock (_statusLock)
{
// 1. 先读取数据并缓存
bool currentEMCStatues = CommonMethods.EMCStatues;
bool currentZupanPLCConnected = false;
bool currentWuliuPLCConnected = false;
if (CommonMethods.plcDevices.Count() > 0)
{
for (int i = 0; i < CommonMethods.plcDevices.Count(); i++)
{
if (CommonMethods.plcDevices[i].IsConnected)
{
if (CommonMethods.plcDevices[i].Name == "PLC_1")
currentZupanPLCConnected = CommonMethods.plcDevices[i].IsConnected;
if (CommonMethods.plcDevices[i].Name == "PLC_2")
{
currentWuliuPLCConnected = CommonMethods.plcDevices[i].IsConnected;
}
}
}
}
bool currentMESLoginStatus = CommonMethods.sysConfig.MesModeSwitching && CommonMethods.mesConfig.IsLoginMesOK;
string currentAlarmText = CommonMethods.SlideAlarmText ?? "";
List<bool> currentStatues = CommonMethods.Statues ?? new List<bool>();
// 2. 只更新变化的数据,避免无意义的UI刷新
this.lbl_DateTime.Text = CurrentTime + " " + week + " " + $"{CommonMethods.strClass}";
if (this.led_RunState.Value != currentEMCStatues)
this.led_RunState.Value = currentEMCStatues;
// PLC连接状态
if (this.led_PLC1State.Value != currentZupanPLCConnected)
this.led_PLC1State.Value = currentZupanPLCConnected;
if (this.led_PLC2State.Value != currentWuliuPLCConnected)
this.led_PLC2State.Value = currentWuliuPLCConnected;
// MES状态:3秒更新一次即可
if (DateTime.Now - _lastMESUpdate > TimeSpan.FromSeconds(3) && this.led_MESState.Value != currentMESLoginStatus)
{
_lastMESUpdate = DateTime.Now;
this.led_MESState.Value = currentMESLoginStatus;
avMesicon.Visible = currentMESLoginStatus;
lblMES.Visible = currentMESLoginStatus;
if (currentMESLoginStatus)
lblMES.Text = CommonMethods.mesConfig.mesUserName;
}
// 只有内容变化时才更新
if (currentStatues.Count > 2 && currentStatues[2])
{
if (this.ucRollText1.Text != currentAlarmText)
{
this.ucRollText1.Text = currentAlarmText;
this.ucRollText1.ForeColor = Color.Red;
}
}
else
{
string noAlarmText = "当前无报警".Translated();
if (this.ucRollText1.Text != noAlarmText)
{
this.ucRollText1.Text = noAlarmText;
this.ucRollText1.ForeColor = Color.White;
CommonMethods.SlideAlarmText = "";
}
}
// LED状态:只在状态变化时更新
if (currentStatues.Count > 0)
{
if (this.led_State.Value != currentStatues[0])
{
this.led_State.Value = currentStatues[0];
this.led_State.BlinkColor = Color.Lime;
this.led_State.OnColor = Color.Lime;
}
bool needBlink = currentStatues.Count > 3 && (currentStatues[1] || currentStatues[2] || currentStatues[3]);
if (this.led_State.BlinkOn != needBlink)
{
this.led_State.BlinkOn = needBlink;
if (needBlink)
{
Color blinkColor = currentStatues[2] ? Color.Red : Color.Yellow;
this.led_State.BlinkColor = blinkColor;
this.led_State.OnColor = blinkColor;
}
}
}
// 登录状态:只在状态变化时更新
bool isSwipeCardMode = CommonMethods.sysConfig.SwipeCardMode && !CommonMethods.IsLoginOk;
if (lbl_LoginName.Visible == isSwipeCardMode)
{
lbl_LoginName.Visible = !isSwipeCardMode;
if (isSwipeCardMode)
lbl_LoginLevel.Text = "未登录";
}
}
System.Diagnostics.Debug.Print("ShowButtonEven_Run end at " + DateTime.Now.ToString("HH:mm:ss.fff"));
}
private void SafeInvoke(Action action)
{
// 1. 基础防护:窗体已释放直接返回
if (this.IsDisposed || !this.IsHandleCreated || action == null)
return;
// 2. 提前声明result并初始化为null,解决“未赋值”编译错误
IAsyncResult result = null;
try
{
if (this.InvokeRequired)
{
// 3. 带超时的BeginInvoke,避免委托堆积
result = this.BeginInvoke(new MethodInvoker(() =>
{
try
{
if (!this.IsDisposed)
action();
}
catch
{
/* 忽略UI更新异常,不影响主线程 */
}
finally
{
// 4. 清理已完成的委托:增加null校验,避免空引用
lock (_pendingInvokes)
{
if (result != null && _pendingInvokes.Contains(result))
{
_pendingInvokes.Remove(result);
}
}
}
}));
// 5. 记录未完成的委托:增加null校验
lock (_pendingInvokes)
{
if (result != null)
{
_pendingInvokes.Add(result);
}
}
// 6. 超时清理:5秒未完成的委托强制取消,避免内存泄漏
Task.Delay(5000).ContinueWith(t =>
{
// 防护:任务取消/异常时不执行
if (t.IsCanceled || t.IsFaulted)
return;
lock (_pendingInvokes)
{
if (result != null && _pendingInvokes.Contains(result) && !result.IsCompleted)
{
try
{
this.EndInvoke(result); // 强制结束未完成的委托
}
catch
{
/* 忽略结束委托的异常(如委托已执行) */
}
_pendingInvokes.Remove(result);
}
}
});
}
else
{
// 7. 无需跨线程:直接执行(加防护)
if (!this.IsDisposed)
action();
}
}
catch
{
// 8. 忽略所有调用异常,避免SafeInvoke自身抛出错误
}
}
///// <summary>
///// 安全执行UI操作(增强版:解决跨线程问题)
///// </summary>
///// <param name="action">要执行的UI操作</param>
///// <param name="timeoutMs">超时时间(默认5000ms)</param>
//private void SafeInvoke(Action action, int timeoutMs = 5000)
//{
// if (action == null) return;
// if (this.IsDisposed || !this.IsHandleCreated) return;
// try
// {
// if (this.InvokeRequired)
// {
// var asyncResult = this.BeginInvoke(action);
// // 等待完成或超时
// if (asyncResult.AsyncWaitHandle.WaitOne(timeoutMs))
// {
// // 正常完成,必须调用EndInvoke
// this.EndInvoke(asyncResult);
// }
// else
// {
// // 超时处理
// Debug.WriteLine($"SafeInvoke超时({timeoutMs}ms)");
// // 超时也需要调用EndInvoke清理资源
// this.EndInvoke(asyncResult);
// }
// }
// else
// {
// action();
// }
// }
// catch (Exception ex)
// {
// Debug.WriteLine($"SafeInvoke异常:{ex.Message}");
// LogHelper.Instance.WriteEX("SafeInvoke异常", ex);
// }
//}
private string CurrentTime
{
get { return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); }
}
private string[] weeks = new string[] { "星期日".Translated(), "星期一".Translated(), "星期二".Translated(), "星期三".Translated(), "星期四".Translated(), "星期五".Translated(), "星期六".Translated() };
private string week
{
get { return weeks[Convert.ToInt32(DateTime.Now.DayOfWeek)]; }
}
#endregion
#region 窗体操作
#region 无边框拖动
private System.Drawing.Point mPoint;
private void Panel_MouseDown(object sender, MouseEventArgs e)
{
mPoint = new System.Drawing.Point(e.X, e.Y);
}
private void Panel_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Location = new System.Drawing.Point(this.Location.X + e.X - mPoint.X, this.Location.Y + e.Y - mPoint.Y);
}
}
#endregion
/// <summary>
/// 关闭程序
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btExit_Click(object sender, EventArgs e)
{
// 关闭窗体
this.Close();
}
private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true; // 先取消关闭
DialogResult dialogResult = new FrmMsgBoxWithAck("是否确定要退出系统".Translated(), "退出系统".Translated()).ShowDialog();
if (dialogResult == DialogResult.OK)
{
try
{
// 1. 停止监听器
CommonMethods.listener.Stop();
// 2. 优雅取消CTS(关键修复:避免回调异常)
if (ControlCenter.Instance != null)
{
// 先取消订阅,避免回调执行
//ControlCenter.Instance.OnCancellationCompleted = null;
// 同步断开PLC(避免异步操作残留)
ControlCenter.Instance.DisconnectAllPlcs();
}
// 3. 取消后台任务
CommonMethods.IsExit = true;
//ControlCenter.Instance._cts?.Cancel();
// 4. 停止所有定时器
updateTimer?.Stop();
storeTimer?.Stop();
updateTimer?.Dispose();
storeTimer?.Dispose();
// 5. 清理委托队列
lock (_pendingInvokes)
{
foreach (var result in _pendingInvokes)
{
if (!result.IsCompleted)
this.EndInvoke(result);
}
_pendingInvokes.Clear();
}
// 6. 释放子窗体缓存
foreach (var frm in _formCache.Values)
{
frm?.Close();
frm?.Dispose();
}
_formCache.Clear();
// 7. 优雅退出
this.Dispose();
Application.Exit();
}
catch (Exception ex)
{
LogHelper.Instance.WriteEX(ex);
// 仅在优雅退出失败时才强制退出
System.Environment.Exit(0);
}
}
else
{
e.Cancel = true;
}
}
}
// 窗体关闭时清理未完成的委托
protected override void OnFormClosing(FormClosingEventArgs e)
{
lock (_pendingInvokes)
{
foreach (var result in _pendingInvokes)
{
if (!result.IsCompleted)
this.EndInvoke(result);
}
_pendingInvokes.Clear();
}
// 停止所有定时器
updateTimer?.Stop();
storeTimer?.Stop();
updateTimer?.Dispose();
storeTimer?.Dispose();
idleTimer?.Stop();
storeTimer?.Dispose();
2026-08-04 18:36:40 +08:00
if (ControlCenter.Instance != null)
{
ControlCenter.Instance.DisconnectAllPlcs(); // 假设存在断开PLC的方法
}
// 4. 延迟释放(给资源清理留时间)
Thread.Sleep(1000);
base.OnFormClosing(e);
}
private void btnScale_Click(object sender, EventArgs e)
{
// 手动触发窗体最小化的逻辑
this.WindowState = FormWindowState.Minimized; // 将窗体最小化
FrmNewMain_Resize(this, EventArgs.Empty); // 调用 Resize 事件处理程序
}
private void FrmNewMain_Resize(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
// 在这里编写窗体最小化时的逻辑
//MessageBox.Show("窗体已最小化");
// 例如:隐藏窗体、显示通知等
}
}
#endregion
#region 左右切换
private void btn_Left_Click(object sender, EventArgs e)
{
CurrentIndex--;
if (CurrentIndex >= 0)
{
CommonNaviButton_Click(naviButton2s[CurrentIndex], null);
}
else
{
CurrentIndex++;
}
}
private void btn_right_Click(object sender, EventArgs e)
{
CurrentIndex++;
if (CurrentIndex < naviButton2s.Count)
{
CommonNaviButton_Click(naviButton2s[CurrentIndex], null);
}
else
{
CurrentIndex--;
}
}
#endregion
#region 通用窗体切换
/// <summary>
/// 通用窗体切换
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CommonNaviButton_Click(object sender, EventArgs e)
{
if (sender is NaviButton2 navi)
{
if (Enum.IsDefined(typeof(FormNames), navi.Tag.ToString()))
{
//拿到导航按钮对应的窗体枚举值
FormNames formNames = (FormNames)Enum.Parse(typeof(FormNames), navi.Tag.ToString(), true);
//用户权限处理
switch (formNames)
{
case FormNames.日志报警:
if (CommonMethods.IsLoginOk)
{
if (!CommonMethods.currentAdmin.SystemLog)
{
new FrmMsgBoxOutWithAck(2, "当前登录用户权限不足!".Translated(), "权限不足".Translated()).ShowDialog();
return;
}
}
else
{
new FrmMsgBoxOutWithAck(2, "请先刷卡登录!".Translated(), "登录系统".Translated()).ShowDialog();
return;
}
break;
case FormNames.数据追溯:
if (CommonMethods.IsLoginOk)
{
if (!CommonMethods.currentAdmin.HistoryData)
{
new FrmMsgBoxOutWithAck(2, "当前登录用户权限不足!".Translated(), "权限不足".Translated()).ShowDialog();
return;
}
}
else
{
new FrmMsgBoxOutWithAck(2, "请先刷卡登录!".Translated(), "登录系统".Translated()).ShowDialog();
return;
}
break;
case FormNames.参数设置:
if (CommonMethods.IsLoginOk)
{
if (!CommonMethods.currentAdmin.ParamSet)
{
new FrmMsgBoxOutWithAck(2, "当前登录用户权限不足!".Translated(), "权限不足".Translated()).ShowDialog();
return;
}
}
else
{
new FrmMsgBoxOutWithAck(2, "请先刷卡登录!".Translated(), "登录系统".Translated()).ShowDialog();
return;
}
break;
case FormNames.系统设置:
if (CommonMethods.IsLoginOk)
{
if (!CommonMethods.currentAdmin.UserManage)
{
new FrmMsgBoxOutWithAck(2, "当前登录用户权限不足!".Translated(), "权限不足".Translated()).ShowDialog();
return;
}
}
else
{
new FrmMsgBoxOutWithAck(2, "请先刷卡登录!".Translated(), "登录系统".Translated()).ShowDialog();
return;
}
break;
case FormNames.用户管理:
if (CommonMethods.IsLoginOk)
{
if (!CommonMethods.currentAdmin.SystemLog)
{
new FrmMsgBoxOutWithAck(2, "当前登录用户权限不足!".Translated(), "权限不足".Translated()).ShowDialog();
return;
}
}
else
{
new FrmMsgBoxOutWithAck(2, "请先刷卡登录!".Translated(), "登录系统".Translated()).ShowDialog();
return;
}
break;
default:
break;
}
//窗体切换
OpenForm(this.MainPanel, formNames);
//设置选中
SetNaviButtonSelected(this.TopPanel, navi);
}
}
}
/// <summary>
/// 通用打开窗体
/// </summary>
/// <param name="mainPanel">容器控件</param>
/// <param name="formNames">窗体枚举名称</param>
private void OpenForm(System.Windows.Forms.Panel mainPanel, FormNames formNames)
{
// 优先从缓存获取窗体
if (_formCache.TryGetValue(formNames, out Form cachedFrm) && !cachedFrm.IsDisposed)
{
cachedFrm.BringToFront();
SetNaviButtonSelected(this.TopPanel, naviButton2s.First(n => n.Tag.ToString() == formNames.ToString()));
return;
}
int total = mainPanel.Controls.Count;
//int closeCount = 0;
bool isFind = false;
foreach (Control ct in mainPanel.Controls)
{
if (ct is Form frm && frm.Text == formNames.ToString())
{
frm.BringToFront();
isFind = true;
break;
}
}
//for (int i = 0; i < total; i++)
//{
// Control ct = mainPanel.Controls[i - closeCount];
// if (ct is Form frm)
// {
// //如果当前Form是我们需要操作的窗体
// if (frm.Text == formNames.ToString())
// {
// frm.BringToFront();
// isFind = true;
// break;
// }
// //如果当前Form不是我们需要操作的窗体,然后判断是否为固定窗体,如果不是,则关闭,如果是,则不做处理
// else if ((FormNames)Enum.Parse(typeof(FormNames), frm.Text, true) >= FormNames.临界窗体)
// {
// frm.Close();
// closeCount++;
// }
// }
//}
if (!isFind)
{
Form frm = null;
switch (formNames)
{
case FormNames.集中监控:
frm = new FrmMonitor();
break;
case FormNames.数据监控:
frm = new FrmDataMonitor();
CommonMethods.AddDataMonitorDelegate += ((FrmDataMonitor)frm).AddDataMonitorLog;//日志记录显示
CommonMethods.ShowFeedingDelegate += ((FrmDataMonitor)frm).ShowFeedingData;//上料显示
CommonMethods.ShowReFeedingDelegate += ((FrmDataMonitor)frm).ShowReFeedingData;//组盘抽检显示
CommonMethods.ShowBlankingDelegate += ((FrmDataMonitor)frm).ShowBankdingData;//下料显示
CommonMethods.ShowTrayDataDelegate += ((FrmDataMonitor)frm).ShowTrayData;//料框码数据显示
CommonMethods.ChangeParamDelegate += ((FrmDataMonitor)frm).GetLocalParaData;//参数更新
break;
case FormNames.日志报警:
frm = new FrmAlarmLog();
CommonMethods.AddLogDelegate += ((FrmAlarmLog)frm).AddLog;//系统日志
CommonMethods.AddOPLogDelegate += ((FrmAlarmLog)frm).AddOPLog;//操作日志
CommonMethods.AddAlarmDelegate += ((FrmAlarmLog)frm).AddAlarm;//报警日志
//CommonMethods.ShowAlarmDelegate += ((FrmAlarmLog)frm).ShowAlarm;
break;
case FormNames.临界窗体:
break;
case FormNames.数据追溯:
frm = new FrmHistory();
break;
case FormNames.参数设置:
frm = new FrmRecipe();
break;
case FormNames.系统设置:
frm = new FrmSystemSet(CommonMethods.deviceConfigPath);
break;
case FormNames.用户管理:
frm = new FrmUserManage();
break;
2026-08-31 13:54:07 +08:00
case FormNames.电池状况:
frm = new FrmBatteryStatus();
CommonMethods.ShowBatteryStatusDelegate += ((FrmBatteryStatus)frm).ShowBatteryStatus;//电池状态显示
CommonMethods.ShowBatteryNGRsnDelegate += ((FrmBatteryStatus)frm).ShowBatteryNGRsn;//档位NG原因显示
CommonMethods.ShowBatteryReplaceDelegate += ((FrmBatteryStatus)frm).ShowBatteryReplace;
break;
2026-08-04 18:36:40 +08:00
//case FormNames.二维码:
// frm = new FrmQRCoder();
// CommonMethods.ShowBatteryQRCoderDelegate += ((FrmQRCoder)frm).ShowBatteryQRCoder;
// break;
default: break;
}
if (frm != null)
{
//设置非顶层窗体
frm.TopLevel = false;
//去除边框
frm.FormBorderStyle = FormBorderStyle.None;
//填充
frm.Dock = DockStyle.Fill;
//设置父容器为容器控件
frm.Parent = mainPanel;
//置前
frm.BringToFront();
frm.Show();
//// 强制刷新布局
//mainPanel.PerformLayout();
//frm.PerformLayout();
}
}
}
/// <summary>
/// 设置导航按钮选中
/// </summary>
/// <param name="topPanel">导航按钮的容器</param>
/// <param name="naviButton">导航按钮</param>
private void SetNaviButtonSelected(System.Windows.Forms.Panel topPanel, NaviButton2 naviButton)
{
foreach (var item in topPanel.Controls.OfType<NaviButton2>())
{
// 仅状态变化时更新,避免无意义重绘
if (item.IsSelected != (item == naviButton))
{
item.IsSelected = (item == naviButton);
}
}
//naviButton.IsSelected = true;
}
#endregion
/// <summary>
/// 获取鼠标光标的当前位置
/// </summary>
/// <param name="pt"></param>
/// <returns></returns>
[DllImport("user32.dll")]
public static extern bool GetCursorPos(out Point pt);
/// <summary>
/// 刷卡用户登录超时检查
/// </summary>
/// <param name="secTime"></param>
private async void UserTimeOut(int secTime)
{
int idleSeconds = 0;
Point lastCursorPos = Point.Empty;
GetCursorPos(out lastCursorPos);
// 忽略5像素内的微小移动
const int MOUSE_MOVE_THRESHOLD = 5;
while (!CommonMethods.LoginOut && idleSeconds < secTime)
{
// 异步延迟1秒,不阻塞线程
await Task.Delay(1000).ConfigureAwait(false);
GetCursorPos(out Point currentCursorPos);
// 检测鼠标是否移动(超过阈值才重置)
int dx = Math.Abs(currentCursorPos.X - lastCursorPos.X);
int dy = Math.Abs(currentCursorPos.Y - lastCursorPos.Y);
if (dx > MOUSE_MOVE_THRESHOLD || dy > MOUSE_MOVE_THRESHOLD)
{
idleSeconds = 0; // 鼠标移动,重置计时
lastCursorPos = currentCursorPos;
}
else
{
idleSeconds++; // 无操作,计时+1
}
}
// 回到UI线程执行退出逻辑
if (idleSeconds >= secTime)
{
this.BeginInvoke(new Action(() => LoginLocalOut()));
}
}
private void LoginLocalOut()
{
CommonMethods.AddOPLog(false, "退出成功".Translated() + "," + "退出用户".Translated() + $":{CommonMethods.currentAdmin?.LoginName}," + "权限".Translated() + $":{CommonMethods.currentAdmin?.LoginLevel}");
LogHelper.Instance.WriteLog("用户".Translated() + $":{CommonMethods.currentAdmin?.LoginName} - " + "退出".Translated());
CommonMethods.LoginOut = true;
CommonMethods.IsLoginOk = false;
2026-08-04 18:36:40 +08:00
}
/// <summary>
/// 切换监控状态
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void btToggleMonitor_Click(object sender, EventArgs e)
{
AntdUI.Button btn = sender as AntdUI.Button;
// 先记录按钮的原始引用,避免异步操作中sender失效
var targetBtn = btn;
if (targetBtn.Text == "START")
{
// 1. 前置校验.通过SafeInvoke确保UI操作在主线程
bool isLoginOk = CommonMethods.IsLoginOk;
bool isMesLoginOk = CommonMethods.sysConfig.MesModeSwitching && CommonMethods.mesConfig.IsLoginMesOK;
string modelName = CommonMethods.mesConfig.ModelName;
string materialCode = "";
// 安全获取UI控件值
SafeInvoke(() =>
{
materialCode = txtMaterialCode.Text.Trim();
});
// 登录校验
if (!isLoginOk)
{
SafeInvoke(() =>
new FrmMsgBoxOutWithAck(2, "当前未登录,请登录!".Translated(), "未登录".Translated()).Show());
return;
}
// MES模式校验
if (CommonMethods.sysConfig.MesModeSwitching && !CommonMethods.mesConfig.IsLoginMesOK)
{
bool mesLoginSuccess = false;
SafeInvoke(() =>
{
new FrmMsgBoxOutWithAck(2, "当前为MES模式,请登录!".Translated(), "MES未登录".Translated()).ShowDialog();
using (FrmLoginMes frmLoginMes = new FrmLoginMes())
{
mesLoginSuccess = frmLoginMes.ShowDialog() == DialogResult.OK;
}
});
if (!mesLoginSuccess) return;
}
// 型号和物料编码校验
if (string.IsNullOrEmpty(modelName))
{
SafeInvoke(() =>
new FrmMsgBoxOutWithAck(2, "产品型号不能为空!".Translated(), "型号选择".Translated()).Show());
return;
}
if (string.IsNullOrEmpty(materialCode))
{
SafeInvoke(() =>
new FrmMsgBoxOutWithAck(2, "物料编码不能为空!".Translated(), "型号选择".Translated()).Show());
return;
}
#region MES下发参数
CommonMethods.mesConfig.MaterialCode = materialCode;
if (CommonMethods.sysConfig.MesModeSwitching && CommonMethods.mesConfig.IsMesParam)
{
var (res, mesg) = await GetMesParaDataAsync().ConfigureAwait(false);
SafeInvoke(() =>
{
if (!res)
{
new FrmMsgBoxOutWithAck(2, mesg, "提示").Show();
}
else
{
CommonMethods.AddDataMonitorLog(1, "MES参数设置成功");
LogHelper.Instance.WriteLog("MES参数设置成功");
}
});
if (!res) return;
}
#endregion
// 安全更新UI:开始连接提示
SafeInvoke(() =>
{
CommonMethods.AddDataMonitorLog(0, "启动开始监控".Translated());
targetBtn.Text = "连接PLC".Translated();
});
// 异步连接PLC(ConfigureAwait(false) 避免捕获当前上下文)
bool IsLink = await ControlCenter.Instance.ConnectAllPlcsAsync().ConfigureAwait(false);
// 所有UI更新必须通过SafeInvoke在主线程执行
SafeInvoke(() =>
{
if (IsLink)
{
CommonMethods.IsRun = true;
targetBtn.Text = "STOP";
targetBtn.DefaultBack = Color.Red; // 按钮背景变为红色
targetBtn.IconSvg = Properties.Resources.StopPLC;
SetProductModelEnable(true);
}
else
{
targetBtn.Text = "START";
targetBtn.DefaultBack = Color.FromArgb(18, 184, 61); // 按钮背景恢复绿色
targetBtn.IconSvg = Properties.Resources.StartPLC;
CommonMethods.AddDataMonitorLog(2, "启动开始监控失败".Translated());
new FrmMsgBoxOutWithAck(2, "连接PLC失败,请检查PLC连接配置,网络".Translated(), "连接PLC".Translated()).Show();
}
});
}
else if (targetBtn.Text == "STOP")
{
// 执行停止监控的逻辑
if (CommonMethods.IsRun)
{
Debug.WriteLine($"Step 1: 开始停止 - {DateTime.Now:HH:mm:ss.fff}");
// 第一步:安全更新UI状态(禁用按钮避免重复点击)
SafeInvoke(() =>
{
targetBtn.Enabled = false;
targetBtn.Text = "停止中...";
SetProductModelEnable(false);
});
try
{
CommonMethods.IsRun = false;
CommonMethods.Statues = new List<bool> { false, false, false, false };
// 第二步:异步停止PLC连接(非UI线程执行)
await Task.Run(() =>
{
Debug.WriteLine($"Step 2: 进入后台线程 - {DateTime.Now:HH:mm:ss.fff}");
try
{
//ControlCenter.Instance.OnCancellationCompleted += cancellationHandler;
// 调用优化后的断开方法
ControlCenter.Instance.DisconnectAllPlcs();
Thread.Sleep(100);
}
catch (Exception ex)
{
Debug.WriteLine($"STOP时断开PLC异常:{ex.Message}");
LogHelper.Instance.WriteEX("STOP PLC异常", ex);
// 异常时也要取消订阅
//if (cancellationHandler != null)
//{
// ControlCenter.Instance.OnCancellationCompleted -= cancellationHandler;
//}
}
Debug.WriteLine($"Step 3: 断开完成 - {DateTime.Now:HH:mm:ss.fff}");
}).ConfigureAwait(false);
Debug.WriteLine($"Step 4: 返回UI线程 - {DateTime.Now:HH:mm:ss.fff}");
// 第三步:安全更新UI
SafeInvoke(() =>
{
Debug.WriteLine($"Step 5: 执行UI更新 - {DateTime.Now:HH:mm:ss.fff}");
CommonMethods.AddDataMonitorLog(0, "停止与PLC连接".Translated());
CommonMethods.AddOPLog(false, "停止与PLC连接".Translated());
// 恢复按钮状态
targetBtn.Text = "START";
targetBtn.DefaultBack = Color.FromArgb(18, 184, 61);
targetBtn.IconSvg = Properties.Resources.StartPLC;
targetBtn.Enabled = true;
});
}
catch (Exception ex)
{
SafeInvoke(() =>
{
CommonMethods.AddDataMonitorLog(2, $"停止失败: {ex.Message}");
// 恢复按钮状态
targetBtn.Text = "STOP";
targetBtn.DefaultBack = Color.Red;
targetBtn.IconSvg = Properties.Resources.StopPLC;
targetBtn.Enabled = true;
new FrmMsgBoxOutWithAck(2, "停止PLC失败,请重试".Translated(), "错误".Translated()).Show();
});
}
}
}
}
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
FrmLogin frmLogin = new FrmLogin();
if (frmLogin.ShowDialog() == DialogResult.OK)
{
CommonMethods.sysConfig.SwipeCardMode = false;
IniConfigHelper.WriteIniData("配置信息", "开启刷卡模式", CommonMethods.sysConfig.SwipeCardMode.ToString());
lbl_LoginLevel.Text = CommonMethods.currentAdmin?.LoginLevel;
lbl_LoginName.Text = CommonMethods.currentAdmin?.LoginName;
lbl_LoginName.Visible = true;
//登录日志
CommonMethods.AddOPLog(false, $"登录成功,登录用户:{CommonMethods.currentAdmin?.LoginName},权限:{CommonMethods.currentAdmin?.LoginLevel}");
}
}
private void cmbModelType_Enter(object sender, EventArgs e)
{
if (cmbModelType.SelectedItem != null)
{
int index = CommonMethods.DropDownItemList.IndexOf(cmbModelType.SelectedItem);
if (index == -1)
cmbModelType.SelectedItem = null;
}
}
/// <summary>
/// 设置产品型号和工单是否只读
/// </summary>
/// <param name="b"></param>
public void SetProductModelEnable(bool b)
{
cmbModelType.Enabled = b;
}
#region 获取参数
/// <summary>
/// 从数据库获取产品型号并绑定到下拉框中
/// </summary>
///
bool IsModelInit = false;
public void SetCombOrg()
{
try
{
txtMaterialCode.Text = "";
CommonMethods.mesConfig.MaterialCode = "";
var productList = CommonMethods.db.QuerySqlList<ProductModel>(CommonMethods.dBSQL.GetProdTypeSql());
if (!IsModelInit)
{
CommonMethods.DropDownItemList.Clear();
for (int i = 0; i < productList.Count; i++)
{
CommonMethods.DropDownItemList.Add(new DropDownListPlusItem() { Text = productList[i].ModelName, Tag = productList[i].MaterialCode });
}
this.cmbModelType.BindItemsSource(CommonMethods.DropDownItemList);
IsModelInit = true;
}
if (productList != null && productList.Count > 0)
{
CommonMethods.mesConfig.ModelName = "";
CommonMethods.mesConfig.MaterialCode = "";
DropDownListPlusItem gg = cmbModelType.SelectedItem;
if (gg != null)
{
CommonMethods.mesConfig.ModelName = gg.Text.ToString();
CommonMethods.mesConfig.MaterialCode = gg.Tag.ToString();
txtMaterialCode.Text = CommonMethods.mesConfig.MaterialCode;
}
}
}
catch (Exception ex)
{
//LogHelper.Instance.WriteEx("获取数据库型号异常", ex);
MessageBox.Show($"获取数据库型号异常:{ex}");
}
}
private void cmbModelType_SelectedItemsChanged(object sender, EventArgs e)
{
if (IsNoOrg && CommonMethods.IsLoginOk)
{
btToggleMonitor.Enabled = true;
IsSetParam = false;
SetCombOrg();
GetLocalParaData();
}
else
{
this.cmbModelType.BindItemsSource(null);
IsModelInit = false;
SetCombOrg();
new FrmMsgBoxOutWithAck(2, "当前未登录,请先登录再操作!", "提示").ShowDialog();
}
}
public void GetLocalParaData()
{
if (string.IsNullOrEmpty(CommonMethods.mesConfig.ModelName))
{
new FrmMsgBoxOutWithAck(2, "产品型号不能为空!", "型号选择").Show();
return;
}
try
{
var list = CommonMethods.db.QuerySqlList<ParamList>(CommonMethods.dBSQL.GetParamSql(CommonMethods.mesConfig.ModelName));
if (list != null && list.Count > 0)
{
CommonMethods.paramlists = list;
IsSetParam = false;
CommonMethods.ChangeParamData();
//GetParam();
}
}
catch (Exception ex)
{
LogHelper.Instance.WriteEX(ex);
}
}
/// <summary>
/// 刷新参数
/// </summary>
//public void GetParam()
//{
// try
// {
// if (!IsSetParam && CommonMethods.paramlists != null)
// {
// System.Windows.Forms.ListViewItem listItem = null;
// lVConfigRange.Items.Clear();
// int j = 0;
// foreach (var ProductPara in CommonMethods.paramlists) //遍历list集合
// {
// string strRemark = ProductPara.Remark;
// string strName = ProductPara.ParaName;
// listItem = new System.Windows.Forms.ListViewItem(CommonMethods.paramlists[j].Remark);
// listItem.SubItems.Add("0");
// listItem.SubItems.Add("0");
// listItem.SubItems.Add("0");
// lVConfigRange.Items.Add(listItem);
// lVConfigRange.Items[j].SubItems[1].Text = ProductPara.ParaValueMin;
// lVConfigRange.Items[j].SubItems[2].Text = ProductPara.ParaValueMax;
// lVConfigRange.Items[j].SubItems[3].Text = ProductPara.Uint;
// switch (strName)
// {
// //case "intoShellPressure1SettingA07": //入壳压力1
// // CommonMethods.parRange.PrePressure1Max = Convert.ToDecimal(ProductPara.ParaValueMax == "" ? "0" : ProductPara.ParaValueMax);
// // break;
// //case "intoShellPressure2SettingA07": //入壳压力2
// // CommonMethods.parRange.PrePressure2Max = Convert.ToDecimal(ProductPara.ParaValueMax == "" ? "0" : ProductPara.ParaValueMax);
// // break;
// //case "intoShellPressure3SettingA07": //入壳压力3
// // CommonMethods.parRange.PrePressure3Max = Convert.ToDecimal(ProductPara.ParaValueMax == "" ? "0" : ProductPara.ParaValueMax);
// // break;
// //default:
// // break;
// }
// j++;
// }
// IsSetParam = true;
// }
// }
// catch (Exception ex)
// {
// LogHelper.Instance.WriteEX("获取参数失败", ex);
// }
//}
/// <summary>
/// 加载MES参数
/// </summary>
public async Task<(bool Success, string msg)> GetMesParaDataAsync()
{
bool Success = false; // 操作结果
string Message = ""; // 消息
try
{
bool isChangeParam = false;
var nowDate = DateTime.Now;
string filePath = $@"{CommonMethods.strMesLogspath}\参数设定值请求\变更记录\{nowDate.Year}\{nowDate.Month}";
string fileName = $@"{nowDate.Day}.csv";
string fileTitle = "时间,机台,MES账户,更改参数名称,更改前参数值,更改后参数值";
string fileContent = string.Empty;
DataTable dt = new DataTable();
dt.Columns.Add("MES账户");
dt.Columns.Add("更改参数名称");
dt.Columns.Add("更改前参数值");
dt.Columns.Add("更改后参数值");
var (resultData, Mesage) = await CommonMethods.hbgMes.GetParamSetRequestAsync(
CommonMethods.mesConfig.DeviceParamChange,
CommonMethods.mesConfig.equipNum,
CommonMethods.mesConfig.siteCode,
CommonMethods.mesConfig.lineCode,
CommonMethods.mesConfig.MaterialCode,
CommonMethods.mesConfig.mesUserName).ConfigureAwait(false);
//var resultData = JsonConvert.DeserializeObject<ParamReturnData>(Data);
if (!resultData.success)
{
// 获取参数未成功
Message = "获取MES参数不成功!";
return (Success, Message);
}
List<ParamList> NewParamlists = CommonMethods.paramlists;
for (int i = 0; i < resultData.total; i++)
{
List<RowsItem> rows = resultData.rows;
for (int j = 0; j < rows.Count; j++)
{
var tagList = rows[j].tagList;
for (int k = 0; k < NewParamlists.Count; k++)
{
for (int n = 0; n < rows[j].tagList.Count; n++)
{
if (NewParamlists[k].ParaName == tagList[n].tagCode)
{
string strMin = "0";
if (String.IsNullOrEmpty(tagList[n].minValue.Trim()) || tagList[n].minValue.Trim() == "null")
strMin = "0";
else
strMin = tagList[n].minValue.Trim();
if (NewParamlists[k].ParaValueMin != strMin)
{
fileContent += $"{nowDate.ToString("yyyy-MM-dd HH:mm:ss")},{CommonMethods.mesConfig.equipNum}," +
$"{CommonMethods.mesConfig.mesUserName},{tagList[n].tagDescription}最小值,{NewParamlists[k].ParaValueMin},{strMin}\n";
dt.Rows.Add(CommonMethods.mesConfig.mesUserName, $"{tagList[n].tagDescription}最小值", NewParamlists[k].ParaValueMin, strMin);
NewParamlists[k].ParaValueMin = strMin;
isChangeParam = true;
}
string strMax = "0";
if (String.IsNullOrEmpty(tagList[n].maxValue.Trim()) || tagList[n].maxValue.Trim() == "null")
strMax = "0";
else
strMax = tagList[n].maxValue.Trim();
if (NewParamlists[k].ParaValueMax != tagList[n].maxValue)
{
fileContent += $"{nowDate.ToString("yyyy-MM-dd HH:mm:ss")},{CommonMethods.mesConfig.equipNum}," +
$"{CommonMethods.mesConfig.mesUserName},{tagList[n].tagDescription}最大值,{NewParamlists[k].ParaValueMax},{strMax}\n";
dt.Rows.Add(CommonMethods.mesConfig.mesUserName, $"{tagList[n].tagDescription}最大值", NewParamlists[k].ParaValueMax, strMax);
NewParamlists[k].ParaValueMax = strMax;
isChangeParam = true;
}
}
}
}
if (isChangeParam)
{
CustomMessageBox customMessageBox = new CustomMessageBox(dt, $"当前MES下发参数与设备本地参数不一致,请确认是否使用MES下发参数");
if (customMessageBox.ShowDialog() == DialogResult.OK)
{
// 写csv文件
fileContent = fileContent.Substring(0, fileContent.Length - 1);
CSVHelper<object>.WriterCSV(filePath, fileName, fileTitle, fileContent);
CommonMethods.paramlists = NewParamlists;
int res = CommonMethods.db.Delete<ParamList>(it => it.ModelName == CommonMethods.paramlists[0].ModelName);
if (res > 0)
{
CommonMethods.db.AddReturnBool<ParamList>(CommonMethods.paramlists);
}
Message = "变更成功并保存";
Success = true;
}
else
{
Message = "取消变更,采用本地参数配置";
}
LogHelper.Instance.WriteLog(Message);
}
}
}
Success = true; // 操作成功
Message = "参数获取成功";
}
catch (Exception ex)
{
Message = "获取参数失败:" + ex.Message;
LogHelper.Instance.WriteEX("获取参数失败", ex);
}
return (Success, Message);
}
#endregion
private void InitializeLanguageSwitch()
{
SwitchLanguage.Items.Clear();
SwitchLanguage.Items.Add(new SelectItem(Properties.Resources.中国国旗, "中文"));
SwitchLanguage.Items.Add(new SelectItem(Properties.Resources.美国国旗, "English"));
SwitchLanguage.Items.Add(new SelectItem(Properties.Resources.匈牙利国旗, "Hungary"));
SwitchLanguage.Items.Add(new SelectItem(Properties.Resources.马来西亚国旗, "Malaysia"));
}
/// <summary>
/// 切换语言
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SwitchLanguage_SelectedValueChanged(object sender, ObjectNEventArgs e)
{
if (e.Value is SelectItem selectedItem)
{
string selectedLanguage = selectedItem.Text;
string languageCode = selectedLanguage switch
{
"中文" => "zh",
"English" => "en",
"Hungary" => "hu",
"Malaysia" => "ms",
_ => "zh"
};
LanguageManager.ChangeLanguage(languageCode);
DgvColumnsClear();
//DgvShiftItemsChange();
}
}
/// <summary>
/// 清除dgv内容
/// </summary>
public void DgvColumnsClear()
{
//清除
if (FrmHistory._Form != null)
{
// 进出站
if (FrmHistory._Form.dgv_Main.Columns != null)
{
if (FrmHistory._Form.dgv_Main.Columns.Count > 0)
{
FrmHistory._Form.dgv_Main.Columns.Clear();
}
}
if (FrmHistory._Form.dgv_Main.Rows != null)
{
if (FrmHistory._Form.dgv_Main.Rows.Count > 0)
{
FrmHistory._Form.dgv_Main.Rows.Clear();
}
}
// 班次
if (FrmHistory._Form.dgvClass.Columns != null)
{
if (FrmHistory._Form.dgvClass.Columns.Count > 0)
{
FrmHistory._Form.dgvClass.Columns.Clear();
}
}
if (FrmHistory._Form.dgvClass.Rows != null)
{
if (FrmHistory._Form.dgvClass.Rows.Count > 0)
{
FrmHistory._Form.dgvClass.Rows.Clear();
}
}
// 日
if (FrmHistory._Form.dgvDays.Columns != null)
{
if (FrmHistory._Form.dgvDays.Columns.Count > 0)
{
FrmHistory._Form.dgvDays.Columns.Clear();
}
}
if (FrmHistory._Form.dgvDays.Rows != null)
{
if (FrmHistory._Form.dgvDays.Rows.Count > 0)
{
FrmHistory._Form.dgvDays.Rows.Clear();
}
}
// 月
if (FrmHistory._Form.dgvMonth.Columns != null)
{
if (FrmHistory._Form.dgvMonth.Columns.Count > 0)
{
FrmHistory._Form.dgvMonth.Columns.Clear();
}
}
if (FrmHistory._Form.dgvMonth.Rows != null)
{
if (FrmHistory._Form.dgvMonth.Rows.Count > 0)
{
FrmHistory._Form.dgvMonth.Rows.Clear();
}
}
// 周
if (FrmHistory._Form.dgvWeek.Columns != null)
{
if (FrmHistory._Form.dgvWeek.Columns.Count > 0)
{
FrmHistory._Form.dgvWeek.Columns.Clear();
}
}
if (FrmHistory._Form.dgvWeek.Rows != null)
{
if (FrmHistory._Form.dgvWeek.Rows.Count > 0)
{
FrmHistory._Form.dgvWeek.Rows.Clear();
}
}
// 报警信息
if (FrmHistory._Form.dgv_AlarmData.Columns != null)
{
if (FrmHistory._Form.dgv_AlarmData.Columns.Count > 0)
{
FrmHistory._Form.dgv_AlarmData.Columns.Clear();
}
}
if (FrmHistory._Form.dgv_AlarmData.Rows != null)
{
if (FrmHistory._Form.dgv_AlarmData.Rows.Count > 0)
{
FrmHistory._Form.dgv_AlarmData.Rows.Clear();
}
}
}
}
/// <summary>
/// 下拉框语言切换
/// </summary>
public void DgvShiftItemsChange()
{
if (FrmHistory._Form != null)
{
FrmHistory._Form.cmb_SelectType.Items.Clear();
FrmHistory._Form.cmb_SelectType.Items.AddRange(new string[] { /*"托盘码打印".Translated(),*/ "电池进站".Translated(), "电池与托盘绑定".Translated(), "电池替换".Translated() });
FrmHistory._Form.cmb_SelectType.SelectedIndex = 0;
FrmHistory._Form.cmbClass.Items.Clear();
FrmHistory._Form.cmbClass.Items.AddRange(new string[] { "白班".Translated(), "夜班".Translated() });
FrmHistory._Form.cmbClass.SelectedIndex = 0;
FrmHistory._Form.cmb_AlarmType.Items.Clear();
FrmHistory._Form.cmb_AlarmType.Items.AddRange(new string[] { "全天".Translated(), "白班".Translated(), "夜班".Translated() });
FrmHistory._Form.cmb_AlarmType.SelectedIndex = 0;
}
}
private string FormatBarcode(string barcode)
{
if (string.IsNullOrEmpty(barcode)) return string.Empty;
int index = barcode.IndexOf('\0');
if (index >= 0)
barcode = barcode.Substring(0, index);
return barcode.Replace("\0", "").Replace("\r", "").Replace(" ", "").Trim();
}
}
#region 枚举定义
public enum FormNames
{
集中监控,
数据监控,
电池状况,
日志报警,
临界窗体,
数据追溯,
参数设置,
系统设置,
用户管理,
//二维码
}
#endregion
#region 消息筛选器
internal class MessageFilter : IMessageFilter
{
//0x0200:鼠标移动
//0x0202:鼠标左键UP
//0x201:鼠标左键Down
//0x0203:鼠标左键双击
//0x0205:鼠标右键UP
//0x0204:鼠标右键Down
//0x020a:鼠标滚轮
//0x100:键盘按下
public bool PreFilterMessage(ref System.Windows.Forms.Message m)
{
//throw new NotImplementedException();
if (m.Msg == 0x0200 || m.Msg == 0x0202 || m.Msg == 0x201 || m.Msg == 0x0203 || m.Msg == 0x0205 || m.Msg == 0x204 || m.Msg == 0x20a || m.Msg == 0x100)
{
CommonMethods.tickCount = 0;
CommonMethods.tickHomeCount = 0;
}
return false;
}
}
#endregion
}