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 PLC; 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 _formCache = new Dictionary(); 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(); /// /// 时间更新委托 /// /// public delegate void ShowTimeHandler(DateTime time); //当前页面索引 private int CurrentIndex = 0; private List naviButton2s = new List(); 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 _cachedModelItems = new List(); // 委托队列(核心优化:防委托堆积) private List _pendingInvokes = new List(); // 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; })); // 双缓冲全覆盖 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; // 定时器初始化优化 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(); } private void btn_logOut_Click(object sender, EventArgs e) { idleTimer.Stop(); // 处理用户超时 this.BeginInvoke(new Action(() => LoginLocalOut())); } 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); //CommonNaviButton_Click(this.nav_BatteryStatus, null); // 登录日志 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后台读取任务 /// /// PLC后台读取专用任务(独立线程,不阻塞UI和其他操作) /// //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 读取配置文件 /// /// 读取配置文件 /// 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 /// /// 刷卡事件 /// /// private void Listener_ScanerEvent(ScanerHook.ScanerCodes codes) { // 非UI线程,必须切UI上下文 //if (this.InvokeRequired) //{ // this.Invoke(new Action(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(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}"); // 如果组盘连接PLC,就下发用户权限 var zupanPlc = CommonMethods.plcDevices.FirstOrDefault(it => it.Name == ConstValue.PLCNAME_ZUPAN); if (zupanPlc == null || !zupanPlc.IsConnected) { return; } Task.Run(async () => await ControlCenter.Instance.SendUserRightToPLCAsync(zupanPlc)); } #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 currentStatues = CommonMethods.Statues ?? new List(); // 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自身抛出错误 } } ///// ///// 安全执行UI操作(增强版:解决跨线程问题) ///// ///// 要执行的UI操作 ///// 超时时间(默认5000ms) //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 /// /// 关闭程序 /// /// /// 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(); 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 通用窗体切换 /// /// 通用窗体切换 /// /// /// 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.SystemSet) { 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; default: break; } //窗体切换 OpenForm(this.MainPanel, formNames); //设置选中 SetNaviButtonSelected(this.TopPanel, navi); } } } /// /// 通用打开窗体 /// /// 容器控件 /// 窗体枚举名称 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; case FormNames.电池状况: frm = new FrmBatteryStatus(); CommonMethods.ShowBatteryStatusDelegate += ((FrmBatteryStatus)frm).ShowBatteryStatus;//电池状态显示 CommonMethods.ShowBatteryNGRsnDelegate += ((FrmBatteryStatus)frm).ShowBatteryNGRsn;//档位NG原因显示 CommonMethods.ShowBatteryReplaceDelegate += ((FrmBatteryStatus)frm).ShowBatteryReplace; break; //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(); } } } /// /// 设置导航按钮选中 /// /// 导航按钮的容器 /// 导航按钮 private void SetNaviButtonSelected(System.Windows.Forms.Panel topPanel, NaviButton2 naviButton) { foreach (var item in topPanel.Controls.OfType()) { // 仅状态变化时更新,避免无意义重绘 if (item.IsSelected != (item == naviButton)) { item.IsSelected = (item == naviButton); } } //naviButton.IsSelected = true; } #endregion /// /// 获取鼠标光标的当前位置 /// /// /// [DllImport("user32.dll")] public static extern bool GetCursorPos(out Point pt); /// /// 刷卡用户登录超时检查 /// /// 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; } /// /// 切换监控状态 /// /// /// 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 { 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; } } /// /// 设置产品型号和工单是否只读 /// /// public void SetProductModelEnable(bool b) { cmbModelType.Enabled = b; } #region 获取参数 /// /// 从数据库获取产品型号并绑定到下拉框中 /// /// bool IsModelInit = false; public void SetCombOrg() { try { txtMaterialCode.Text = ""; CommonMethods.mesConfig.MaterialCode = ""; var productList = CommonMethods.db.QuerySqlList(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(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); } } /// /// 刷新参数 /// //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); // } //} /// /// 加载MES参数 /// 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(Data); if (!resultData.success) { // 获取参数未成功 Message = "获取MES参数不成功!"; return (Success, Message); } List NewParamlists = CommonMethods.paramlists; for (int i = 0; i < resultData.total; i++) { List 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.WriterCSV(filePath, fileName, fileTitle, fileContent); CommonMethods.paramlists = NewParamlists; int res = CommonMethods.db.Delete(it => it.ModelName == CommonMethods.paramlists[0].ModelName); if (res > 0) { CommonMethods.db.AddReturnBool(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")); } /// /// 切换语言 /// /// /// 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(); } } /// /// 清除dgv内容 /// 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(); } } } } /// /// 下拉框语言切换 /// 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 }