Files
1258/LargeSquareOne/FrmMain.cs
T
Administrator c2ed98d52d 20260831功能同步:
1. 不同车间区分料框查询、料框解绑接口
2. 注释电池型号逻辑
3. 打开电池状况界面
2026-08-31 13:54:07 +08:00

2003 lines
81 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using 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;
}));
// 双缓冲全覆盖
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 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后台读取任务
/// <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();
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;
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();
}
}
}
/// <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;
}
/// <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
}