Files
kou_zhaoxielou_shandong/口罩泄露定制款/Form/frm_Main.cs
2026-01-22 19:18:16 +08:00

2342 lines
97 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 DevExpress.ClipboardSource.SpreadsheetML;
using DevExpress.Internal;
using DevExpress.XtraPrinting;
using Modbus.Device;
using Newtonsoft.Json;
using OfficeOpenXml;
using OfficeOpenXml.Drawing.Slicer.Style;
using SQLite;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using .Data;
using .Excle;
using .Form;
using .Log;
using .Modbus;
using _定制款.;
namespace
{
public partial class frm_Main : UIForm
{
// 暂停功能相关变量
private bool isPaused = false;
private int pausedRemainingSeconds = 0;
private string currentVideoPath = string.Empty;
UserExcleHelper excleHelper = new UserExcleHelper();
LoginData loginData = new LoginData();
Modbus_Connect modbus_Connect;
public ModbusMaster master;
Connect_TSI Tsi;
ExperData experData = new ExperData();
Function fc;
BoolSignal bool_Stop = new BoolSignal();
BoolSignal bool_Start = new BoolSignal();
DataTable dt_Show = new DataTable();
ExperData_ExcleHelper experExcleHelper = new ExperData_ExcleHelper();
private Logger _logger = new Logger();
frm_vidio form2 = new frm_vidio();
bool isNG = false;
// 1. 成员变量
private List<string> stepList = new List<string>();
private int currentStepIndex = 0;
private System.Windows.Forms.Timer autoStepTimer;
private System.Windows.Forms.Timer autoStepTimer2;
private int countdownSeconds = 120;//add by xyy,原版120s
private bool isNeedRun = false;
private string CreenValue = string.Empty;
private const string UserDataFilePath = "UserData.json"; // JSON 文件路径
// 2. 配置读取
private void LoadIsNeedRunConfig()
{
string configPath = Path.Combine(Application.StartupPath, "UserData.json");
if (File.Exists(configPath))
{
var json = File.ReadAllText(configPath);
dynamic config = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
isNeedRun = config?.IsNeedRun == true;//是否运行跑步机
if (config?.ContentString == "自定义")//大声朗读内容
{
CreenValue = config?.CustomScreenValue;
}
else
{
CreenValue = config?.ScreenValue;
}
}
}
// 步骤初始化 - 根据新标准调整
private void InitStepList()
{
stepList.Clear();
stepList.Add("请到指定测试位置");
stepList.Add("请将采样管插头插入测量接口");
if (isNeedRun)
stepList.Add("请按下跑步机启动按钮");
stepList.Add("头部静止、不说话2 min");
stepList.Add("左右转动头部看检测仓左右墙壁(大约15次)2 min");
stepList.Add("抬头和低头看检测仓顶和地面(大约15次)2 min");
stepList.Add("大声阅读屏幕显示文字2 min");
stepList.Add("头部静止、不说话2 min");
stepList.Add("测试完成,拔下采样管插头,走出测量仓");
comboBox1.Items.Clear();
foreach (var step in stepList)
comboBox1.Items.Add(step);
}
// 4. 自动流程Timer
private void InitAutoStepTimer()
{
if (autoStepTimer == null)
{
autoStepTimer = new System.Windows.Forms.Timer();
autoStepTimer.Interval = 1000;
autoStepTimer.Tick += (s, e) =>
{
countdownSeconds--;
lb_status.Text = $"{stepList[currentStepIndex]} 倒计时: {countdownSeconds}秒";
// 更新form2的标签文本保留原有内容只更新倒计时部分
int index = form2.uiLabel1.Text.LastIndexOf("\r\n倒计时:");
if (index > 0)
{
form2.uiLabel1.Text = form2.uiLabel1.Text.Substring(0, index) + $"\r\n倒计时: {countdownSeconds}秒";
}
//form2.axWindowsMediaPlayer1.settings.autoStart = true; // 设置自动播放
//form2.axWindowsMediaPlayer1.Ctlcontrols.play();
if (countdownSeconds <= 0)
{
autoStepTimer?.Stop();
GoToNextStep();
}
};
}
//countdownTimer = new System.Windows.Forms.Timer();
//countdownTimer.Interval = 1000; // 1 second interval
// countdownTimer.Tick += new EventHandler(CountdownTimer_Tick);
}
private void InitAutoStepTimer2()
{
if (autoStepTimer2 == null)
{
autoStepTimer2 = new System.Windows.Forms.Timer();
autoStepTimer2.Interval = 1000;
autoStepTimer2.Tick += (s, e) =>
{
if (float.Parse(lb_tsi_Indoor.Text) < 7)
{
master?.WriteSingleCoil(1, 16, true);
}
else if (float.Parse(lb_tsi_Indoor.Text) > 8)
{
master?.WriteSingleCoil(1, 16, false);
}
else
{
}
//if (currentStepIndex == 1 && float.Parse(lb_tsi_Indoor.Text) >= 4)
//{
// currentStepIndex = 2;
// GoToStep(2);
//}
//else
//{
//}
};
}
}
// 5. 流程控制
private void StartProcess()
{
currentStepIndex = 0;
GoToStep(currentStepIndex);
}
private void GoToNextStep()
{
currentStepIndex++;
GoToStep(currentStepIndex);
}
private void GoToStep(int index)
{
isPaused = false;
Pause1.Text = "暂停测试";
Pause1.Style = UIStyle.Red;
// 检查是否超出步骤列表范围
if (index >= stepList.Count)
{
lb_status.Text = "所有流程已完成!";
form2.uiLabel1.Text = "所有流程已完成!";
//btn_NextStep.Enabled = false;
//master?.WriteSingleCoil(1, 15, false);
master?.WriteSingleCoil(1, 16, false);
autoStepTimer?.Stop();
autoStepTimer2?.Stop();
StopVideo(); // 确保视频停止
return;
}
// 更新选中步骤和状态文本
comboBox1.SelectedIndex = index;
string baseStepText = stepList[index];
lb_status.Text = baseStepText;
// 更新form2的标签文本
form2.uiLabel1.Text = stepList[index].Contains("大声阅读屏幕显示文字")
? (baseStepText + "\r\n" + CreenValue)
: baseStepText;
// 处理视频路径(保持原有逻辑)
string basePath = AppDomain.CurrentDomain.BaseDirectory;
string videoPath = "";
if (isNeedRun)
{
switch (index)
{
case 3: videoPath = Path.Combine(basePath, "头部静止.MP4"); break;
case 4: videoPath = Path.Combine(basePath, "左右转头.MP4"); break;
case 5: videoPath = Path.Combine(basePath, "上下抬头.MP4"); break;
case 6: videoPath = Path.Combine(basePath, "大声说话.MP4"); break;
case 7: videoPath = Path.Combine(basePath, "头部静止.MP4"); break;
default: videoPath = string.Empty; break;
}
// 标记当前步骤是否为需要延迟执行AddDgv的步骤
bool isDelayAddDgvStep = index > 2 && index < 8;
if (isDelayAddDgvStep)
{
//master?.WriteSingleCoil(1, 16, true); 1
Thread.Sleep(100);
// 修复:使用完整的事件处理方法语法
EventHandler handler = null;
handler = new EventHandler((s, e) =>
{
if (countdownSeconds <= 1)
{
AddDgv();
//// 移除事件(避免重复执行)
autoStepTimer.Tick -= handler;
}
});
autoStepTimer.Tick += handler;
}
else
{
//master?.WriteSingleCoil(1, 16, false); 2
Thread.Sleep(100);
}
}
else
{
switch (index)
{
case 2: videoPath = Path.Combine(basePath, "头部静止.MP4"); break;
case 3: videoPath = Path.Combine(basePath, "左右转头.MP4"); break;
case 4: videoPath = Path.Combine(basePath, "上下抬头.MP4"); break;
case 5: videoPath = Path.Combine(basePath, "大声说话.MP4"); break;
case 6: videoPath = Path.Combine(basePath, "头部静止.MP4"); break;
default: videoPath = string.Empty; break;
}
// 标记当前步骤是否为需要延迟执行AddDgv的步骤
bool isDelayAddDgvStep = index > 1 && index < 7;
if (isDelayAddDgvStep)
{
//master?.WriteSingleCoil(1, 16, true); 1
Thread.Sleep(100);
// 修复:使用完整的事件处理方法语法
EventHandler handler = null;
handler = new EventHandler((s, e) =>
{
if (countdownSeconds <= 1)
{
AddDgv();
// 移除事件(避免重复执行)
autoStepTimer.Tick -= handler;
}
});
autoStepTimer.Tick += handler;
}
else
{
//master?.WriteSingleCoil(1, 16, false); 2
Thread.Sleep(100);
}
}
if (index == 0)
{
master?.WriteSingleCoil(1, 15, false);
}
if (index == 1)
{
autoStepTimer2.Start();
}
if (index == 2)
{
master?.WriteSingleCoil(1, 15, true);
}
if (index == 7)
{
master?.WriteSingleCoil(1, 15, false);
}
// 控制视频播放
if (!string.IsNullOrEmpty(videoPath) && File.Exists(videoPath))
{
form2.axWindowsMediaPlayer1.URL = videoPath;
form2.axWindowsMediaPlayer1.Ctlcontrols.play();
}
else
{
StopVideo();
}
// 新的倒计时逻辑前三步0-230秒后续4-9步3-8120秒
bool isCountdownStep = index >= 0 && index <= 8;
if (isCountdownStep)
{
// 根据步骤索引设置倒计时秒数原版前三步30秒后续120秒
countdownSeconds = index < 2 ? 30 : index == 7 ? 10 : 120;
// 更新状态文本,包含倒计时信息
lb_status.Text = $"{baseStepText} 倒计时: {countdownSeconds}秒";
form2.uiLabel1.Text = $"{form2.uiLabel1.Text}\r\n倒计时: {countdownSeconds}秒";
// 启动计时器
autoStepTimer?.Start();
}
else
{
// 不在倒计时范围内,停止计时器
autoStepTimer?.Stop();
}
}
public void RefreshMainData()
{
LoadIsNeedRunConfig(); // 先读取配置
InitStepList(); // 再初始化流程步骤和下拉框
}
// 新增:停止视频播放并清除路径的辅助方法
private void StopVideo()
{
form2.axWindowsMediaPlayer1.Ctlcontrols.stop();
form2.axWindowsMediaPlayer1.URL = string.Empty;
}
public frm_Main()
{
InitializeComponent();
comboBox1.SelectedIndex = 0;
}
#region
private void frm_Main_Load(object sender, EventArgs e)
{
try
{
Pause1.Text = "暂停测试";
Pause1.Style = UIStyle.Red;
///add by xyy
LoadIsNeedRunConfig(); // 先读取配置
InitStepList(); // 再初始化流程步骤和下拉框
//add by xyy 192.168.1.10先改100
modbus_Connect = new Modbus_Connect("192.168.1.10", 502);
master = modbus_Connect.GetMaster();
master?.WriteSingleCoil(1, 132, false);
Task.Run(() => Read_PLC_Data());
fc = new Function(master);
comboBox1.Enabled = false;
//form2.axWindowsMediaPlayer1.PlayStateChange +=
// new AxWMPLib._WMPOCXEvents_PlayStateChangeEventHandler(
// axWindowsMediaPlayer1_PlayStateChange);
}
catch (Exception EX)
{
MessageBox.Show("控制器连接失败!" + "\n" + "错误原因:" + EX.Message, "错误");
}
try
{
Tsi = new Connect_TSI("COM18", "COM8");
Tsi.Connect();
Tsi.Start_Indoor();
Tsi.Start_Outdoor();
Tsi.Start_bendidoor();
}
catch (Exception ex)
{
MessageBox.Show("光度计连接失败!" + "\n" + "错误原因:" + ex.Message, "错误");
}
bool_Stop.OnRisingEdge += bool_Stop_OnRisingEdge;
// bool_Start.OnRisingEdge += bool_Start_OnRisingEdge;
Task.Run(() =>
{
while (true)
{
bool_Stop.Value = data_M130_M135[2];
bool_Start.Value = data_M130_M135[0];
//bool_Stop.Value = false;//add by xyy
//bool_Stop.Value = true;//add by xyy
bool_Stop.CheckRisingEdge();
bool_Start.CheckRisingEdge();
Thread.Sleep(10);
}
});
tslb_登录用户.Text = loginData.UserName;
UserAuthority();
InitializeDgv();
experData.TestStatus = comboBox1.Text;
_logger.Log(experData.ExperName, "登陆系统", loginData.UserPower.ToString());
form2.Show();
}
void InitializeDgv()
{
dt_Show.Columns.Add("姓名");
dt_Show.Columns.Add("性别");
dt_Show.Columns.Add("年龄");
dt_Show.Columns.Add("身份证号码");
dt_Show.Columns.Add("工作单位");
dt_Show.Columns.Add("工龄");
dt_Show.Columns.Add("日期");
dt_Show.Columns.Add("时间");
dt_Show.Columns.Add("实验员");
dt_Show.Columns.Add("样品编号");
dt_Show.Columns.Add("样品类别");
dt_Show.Columns.Add("测试状态");
dt_Show.Columns.Add("环境温度(℃)");
dt_Show.Columns.Add("环境湿度(%RH)");
dt_Show.Columns.Add("本底浓度(mg/m³)");
dt_Show.Columns.Add("室内浓度平均值(mg/m³)");
dt_Show.Columns.Add("呼吸器内气溶胶平均值(mg/m³)");
dt_Show.Columns.Add("泄露率(%)");
dgv_expirData.DataSource = dt_Show;
dgv_expirData.Font = new System.Drawing.Font("黑体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
dgv_expirData.Columns[12].Width = 250;
dgv_expirData.Columns[13].Width = 250;
dgv_expirData.Columns[14].Width = 200;
dgv_expirData.Columns[15].Width = 250;
dgv_expirData.Columns[16].Width = 250;
}
//void AddDgv()
//{
// float _TsiIndoorAgv = 0.0f;
// float _TsiOutdoorAgv = 0.0f;
// float _Xieloulv = 0.0f;
// if (dt_Show.Columns.Count != 0)
// {
// if (list_Tsi_Indoor_Data.Count != 0 && list_Tsi_Outdoor_Data.Count != 0)
// {
// _TsiIndoorAgv = list_Tsi_Indoor_Data.Average();
// _TsiOutdoorAgv = list_Tsi_Outdoor_Data.Average();
// _Xieloulv = lsit_XieLoulv.Average();
// }
// else
// {
// _TsiIndoorAgv = 0.0f;
// _TsiOutdoorAgv = 0.0f;
// _Xieloulv = 0.0f;
// }
// 口罩泄露测试仪控制系统_定制款.窗体.UserData userData = new 口罩泄露测试仪控制系统_定制款.窗体.UserData();
// if (File.Exists(UserDataFilePath))
// {
// string json = File.ReadAllText(UserDataFilePath);
// userData = JsonConvert.DeserializeObject<口罩泄露测试仪控制系统_定制款.窗体.UserData>(json);
// }
// dt_Show.Rows.Add(
// userData?.Name,
// userData?.Sex,
// userData?.Age,
// userData?.IdNumber,
// userData?.Company,
// userData?.CompanyAge,
// DateTime.Now.ToString("yyyy-MM-dd"),
// DateTime.Now.ToString("HH-mm-ss"),
// experData.ExperName,
// experData.ExperNum,
// experData.ExperType,
// comboBox1.Text,
// experData.HuanJingWenDu,
// experData.HuanJingShiDu,
// experData.BenDiNongDu,
// _TsiIndoorAgv,
// _TsiOutdoorAgv,
// _Xieloulv);
// this.Invoke(new Action(() =>
// {
// dgv_expirData.Refresh();
// InsertDataToDatabase();
// }));
// }
// // dt_Show.Rows.Add("1","2","3","4","5","6","7","8","9","10");
//}
void AddDgv()
{
float _TsiIndoorAgv = 0.0f;
float _TsiOutdoorAgv = 0.0f;
float _Xieloulv = 0.0f;
if (dt_Show.Columns.Count != 0)
{
// 使用最后100秒数据计算标准要求
int dataCount = Math.Min(list_Tsi_Indoor_Data.Count, list_Tsi_Outdoor_Data.Count);
int startIndex = Math.Max(0, dataCount - 100);
List<float> last100Indoor = new List<float>();
List<float> last100Outdoor = new List<float>();
for (int i = startIndex; i < dataCount; i++)
{
last100Indoor.Add(list_Tsi_Indoor_Data[i]);
last100Outdoor.Add(list_Tsi_Outdoor_Data[i]);
}
if (last100Indoor.Count > 0 && last100Outdoor.Count > 0)
{
_TsiIndoorAgv = last100Indoor.Average();
_TsiOutdoorAgv = last100Outdoor.Average();
// 使用连续采样法计算公式
_Xieloulv = experData.ContinuousSamplingLeakageRate(
last100Indoor,
last100Outdoor,
experData.BenDiNongDu,
experData.SamplingFlowRate,
experData.DryingFlowRate);
}
else
{
_TsiIndoorAgv = 0.0f;
_TsiOutdoorAgv = 0.0f;
_Xieloulv = 0.0f;
}
_定制款..UserData userData = new _定制款..UserData();
if (File.Exists(UserDataFilePath))
{
string json = File.ReadAllText(UserDataFilePath);
userData = JsonConvert.DeserializeObject<_定制款..UserData>(json);
}
dt_Show.Rows.Add(
userData?.Name,
userData?.Sex,
userData?.Age,
userData?.IdNumber,
userData?.Company,
userData?.CompanyAge,
DateTime.Now.ToString("yyyy-MM-dd"),
DateTime.Now.ToString("HH-mm-ss"),
experData.ExperName,
experData.ExperNum,
experData.ExperType,
comboBox1.Text,
experData.HuanJingWenDu.ToString("F1"),
experData.HuanJingShiDu.ToString("F1"),
experData.BenDiNongDu.ToString("F3"),
_TsiIndoorAgv.ToString("F3"),
_TsiOutdoorAgv.ToString("F3"),
_Xieloulv.ToString("F2"));
this.Invoke(new Action(() =>
{
dgv_expirData.Refresh();
InsertDataToDatabase();
}));
}
}
private void InsertDataToDatabase()
{
float _Xieloulv = 0.0f;
_Xieloulv = experData.ContinuousSamplingLeakageRate(
list_Tsi_Indoor_Data,
list_Tsi_Outdoor_Data,
experData.BenDiNongDu,
experData.SamplingFlowRate,
experData.DryingFlowRate);
// 读取用户数据
_定制款..UserData userData = new _定制款..UserData();
if (File.Exists(UserDataFilePath))
{
string json = File.ReadAllText(UserDataFilePath);
userData = JsonConvert.DeserializeObject<_定制款..UserData>(json);
}
// 创建 SQLite 连接并初始化
string dbPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data.db");
SQLiteConnection _db = new SQLiteConnection(dbPath);
_db.CreateTable<Experiment>();
// 构建 Experiment 对象
Experiment experiment = new Experiment
{
Name = userData?.Name,
Sex = userData?.Sex,
Age = userData?.Age != null ? int.Parse(userData.Age) : (int?)null,
IdNumber = userData?.IdNumber,
Company = userData?.Company,
CompanyAge = userData?.CompanyAge != null ? int.Parse(userData.CompanyAge) : (int?)null,
Date = DateTime.Now.ToString("yyyy-MM-dd"),
Time = DateTime.Now.ToString("HH-mm-ss"),
ExperName = experData.ExperName,
//ExperNum = experData.ExperNum,
ExperType = experData.ExperType,
MaskType = userData.FullMaskType,
TestStatus = comboBox1.Text,
HuanJingWenDu = experData.HuanJingWenDu,
HuanJingShiDu = experData.HuanJingShiDu,
BenDiNongDu = experData.BenDiNongDu,
TsiIndoorAgv = list_Tsi_Indoor_Data.Any() ? list_Tsi_Indoor_Data.Average() : 0,
TsiOutdoorAgv = list_Tsi_Outdoor_Data.Any() ? list_Tsi_Outdoor_Data.Average() : 0,
Xieloulv = _Xieloulv //lsit_XieLoulv.Any() ? lsit_XieLoulv.Average() : 0
};
// 插入数据
try
{
_db.Insert(experiment);
}
catch (Exception ex)
{
// 处理异常,这里可以根据实际需求进行日志记录或者弹窗提示等
Console.WriteLine($"插入数据失败: {ex.Message}");
}
finally
{
_db.Close();
}
}
//private void InsertDataToDatabase()
//{
// // 读取用户数据
// 口罩泄露测试仪控制系统_定制款.窗体.UserData userData = new 口罩泄露测试仪控制系统_定制款.窗体.UserData();
// if (File.Exists(UserDataFilePath))
// {
// string json = File.ReadAllText(UserDataFilePath);
// userData = JsonConvert.DeserializeObject<口罩泄露测试仪控制系统_定制款.窗体.UserData>(json);
// }
// // 创建 SQLite 连接并初始化
// string dbPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data.db");
// SQLiteConnection _db = new SQLiteConnection(dbPath);
// _db.CreateTable<Experiment>();
// // 构建 Experiment 对象
// Experiment experiment = new Experiment
// {
// Name = userData?.Name,
// Sex = userData?.Sex,
// Age = userData?.Age != null ? int.Parse(userData.Age) : (int?)null,
// IdNumber = userData?.IdNumber,
// Company = userData?.Company,
// CompanyAge = userData?.CompanyAge != null ? int.Parse(userData.CompanyAge) : (int?)null,
// Date = DateTime.Now.ToString("yyyy-MM-dd"),
// Time = DateTime.Now.ToString("HH-mm-ss"),
// ExperName = experData.ExperName,
// //ExperNum = experData.ExperNum,
// ExperType = experData.ExperType,
// MaskType = userData.FullMaskType,
// TestStatus = comboBox1.Text,
// HuanJingWenDu = experData.HuanJingWenDu,
// HuanJingShiDu = experData.HuanJingShiDu,
// BenDiNongDu = experData.BenDiNongDu,
// TsiIndoorAgv = list_Tsi_Indoor_Data.Any() ? list_Tsi_Indoor_Data.Average() : 0,
// TsiOutdoorAgv = list_Tsi_Outdoor_Data.Any() ? list_Tsi_Outdoor_Data.Average() : 0,
// Xieloulv = lsit_XieLoulv.Any() ? lsit_XieLoulv.Average() : 0
// };
// // 插入数据
// try
// {
// _db.Insert(experiment);
// }
// catch (Exception ex)
// {
// // 处理异常,这里可以根据实际需求进行日志记录或者弹窗提示等
// Console.WriteLine($"插入数据失败: {ex.Message}");
// }
// finally
// {
// _db.Close();
// }
//}
Random rd = new Random();
private void timer_date_Tick(object sender, EventArgs e)
{
//刷新时间
tslb_time.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
//刷新界面数据
Resfh_UI_Data();
}
private void Resfh_UI_Data()
{
tslb_实验类型.Text = experData.ExperType;
tslb_实验编号.Text = experData.ExperNum;
lb_YangNongdu.Text = experData.O2NongDu.ToString("F2");
lb_shiDu.Text = experData.HuanJingShiDu.ToString("F2");
lb_wenDu.Text = experData.HuanJingWenDu.ToString("F2");
lb_CO2_Indoor.Text = experData.CO2NongDu_Indoor.ToString("F2");
lb_co2_OutDoor.Text = experData.Mask_CO2NongDu.ToString("F2");
lb_tsi_Indoor.Text = experData.InDoor_TSINongDu.ToString("F3");
lb_tsi_OutDoor.Text = experData.Mask_TSINongDu.ToString("F3");
lb_泄露率.Text = experData.XieLouLv.ToString("F2");
label16.Text = TestTime.ToString();
if (data_M6_M7[1])
{ btn_Light.Text = "照明关"; btn_Light.ForeColor = System.Drawing.Color.Red; }
else
{ btn_Light.Text = "照明开"; btn_Light.ForeColor = System.Drawing.Color.Black; }
if (data_M6_M7[0])
{ btn_风机.Text = "风机关"; btn_风机.ForeColor = System.Drawing.Color.Red; }
else
{ btn_风机.Text = "风机开"; btn_风机.ForeColor = System.Drawing.Color.Black; }
}
//用户权限判断
void UserAuthority()
{
switch (loginData.UserPower)
{
case 0:
ts_新建实验.Enabled = true;
ts_参数设置.Enabled = true;
ts_实验数据.Enabled = true;
ts_审计追踪.Enabled = true;
ts_用户管理.Enabled = true;
tsbtn_新增用户.Enabled = true;
toolStripButton1.Enabled = true;
break;
case 1:
ts_新建实验.Enabled = true;
ts_参数设置.Enabled = true;
ts_实验数据.Enabled = true;
ts_审计追踪.Enabled = true;
ts_用户管理.Enabled = false;
tsbtn_新增用户.Enabled = true;
toolStripButton1.Enabled = false;
break;
case 2:
ts_新建实验.Enabled = true;
ts_参数设置.Enabled = false;
ts_实验数据.Enabled = true;
ts_审计追踪.Enabled = false;
ts_用户管理.Enabled = false;
tsbtn_新增用户.Enabled = false;
toolStripButton1.Enabled = false;
break;
case 3:
ts_新建实验.Enabled = true;
ts_参数设置.Enabled = false;
ts_实验数据.Enabled = false;
ts_审计追踪.Enabled = false;
ts_用户管理.Enabled = false;
tsbtn_新增用户.Enabled = false;
toolStripButton1.Enabled = false;
break;
case 4:
ts_新建实验.Enabled = false;
ts_参数设置.Enabled = false;
ts_实验数据.Enabled = false;
ts_审计追踪.Enabled = false;
ts_用户管理.Enabled = false;
tsbtn_新增用户.Enabled = false;
toolStripButton1.Enabled = false;
break;
}
}
#endregion
#region
private void tsbtn_新增用户_Click(object sender, EventArgs e)
{
frm_AddUser addUser = new frm_AddUser();
addUser.ShowDialog();
}
private void tsbtn_切换用户_Click(object sender, EventArgs e)
{
this.Close();
}
private void ts_用户管理_Click(object sender, EventArgs e)
{
frm_UserSetting userSetting = new frm_UserSetting();
userSetting.ShowDialog();
}
private void ts_审计追踪_Click(object sender, EventArgs e)
{
frm_Audit_Trail audit_Trail = new frm_Audit_Trail();
audit_Trail.ShowDialog();
}
private void ts_新建实验_Click(object sender, EventArgs e)
{
frm_AddNewExperiment addUser = new frm_AddNewExperiment(this);
addUser.ShowDialog();
}
private void ts_参数设置_Click(object sender, EventArgs e)
{
frm_ExperSetting experSetting = new frm_ExperSetting(master);
experSetting.ShowDialog();
}
private void ts_实验数据_Click(object sender, EventArgs e)
{
frm_ExperData experData = new frm_ExperData();
experData.ShowDialog();
}
#endregion
#region
private void frm_Main_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
{
Tsi.Stop_Indoor();
Tsi.Stop_Outdoor();
Tsi.Stop_bendidoor();
Tsi.Disconnect();
modbus_Connect.DisConnect();
this.Dispose();
}
#endregion
#region PLC数据读取
ushort[] data_D300_D320 = new ushort[21];
ushort[] data_D250_D299 = new ushort[50];
ushort[] data_D400_D499 = new ushort[100];
ushort[] data_D500_D507 = new ushort[8];
bool[] data_M6_M7 = new bool[2];
bool[] data_M60_M65 = new bool[6];
bool[] data_M90_M95 = new bool[6];
bool[] data_M130_M135 = new bool[6];
DataChange dc = new DataChange();
int TestTime = 0;
void Read_PLC_Data()
{
while (true)
{
if (this.IsDisposed || master == null)
{
break;
}
try
{
//读取PLC数据
data_D300_D320 = master?.ReadHoldingRegisters(1, 300, 20);
data_D250_D299 = master?.ReadHoldingRegisters(1, 250, 50);
data_D400_D499 = master?.ReadHoldingRegisters(1, 400, 100);
data_D500_D507 = master?.ReadHoldingRegisters(1, 500, 8);
data_M6_M7 = master?.ReadCoils(1, 6, 2);
data_M60_M65 = master?.ReadCoils(1, 60, 6);
data_M90_M95 = master?.ReadCoils(1, 90, 6);
data_M130_M135 = master?.ReadCoils(1, 130, 6);
//显示PLC数据
experData.LiuLiang = dc.UshortToFloat(data_D300_D320[1], data_D300_D320[0]);
experData.Mask_CO2NongDu = dc.UshortToFloat(data_D300_D320[3], data_D300_D320[2]);
experData.CO2NongDu_Indoor = dc.UshortToFloat(data_D300_D320[5], data_D300_D320[4]);
experData.O2NongDu = dc.UshortToFloat(data_D300_D320[7], data_D300_D320[6]);
experData.HuanJingWenDu = dc.UshortToFloat(data_D300_D320[9], data_D300_D320[8]);
experData.HuanJingShiDu = dc.UshortToFloat(data_D300_D320[11], data_D300_D320[10]);
experData.InDoor_TSINongDu = Tsi.Indoor_Data;//modified by xyy
experData.Mask_TSINongDu = Tsi.Outdoor_Data;//modified by xyy
//experData.BenDiNongDu = Tsi.sp_bendiData.ToFloat();
TestTime = dc.UshortToInt1(data_D250_D299[0], data_D250_D299[1]);
Thread.Sleep(100);
}
catch
{
break;
}
}
}
#endregion
private void btn_Light_Click(object sender, EventArgs e)
{
fc.BtnClickFunction(Function.ButtonType., 7);
}
private void btn_风机_Click(object sender, EventArgs e)
{
fc.BtnClickFunction(Function.ButtonType., 6);
}
private void toolStripButton1_Click(object sender, EventArgs e)
{
frm_Motor _Motor = new frm_Motor(master);
_Motor.ShowDialog();
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
int idx = comboBox1.SelectedIndex;
if (idx < 0 || idx >= stepList.Count)
return;
string step = stepList[idx];
lb_status.Text = step;
// 判断是否为“朗读文字”步骤
if (step.Contains("大声阅读屏幕显示文字"))
{
form2.uiLabel1.Text = step;
form2.uiLabel1.Text += CreenValue;
}
else
{
form2.uiLabel1.Text = step;
}
_logger.Log(loginData.UserName, $"切换了实验状态为【{step}】", loginData.UserPower.ToString());
}
#region
List<List<List<float>>> list_AllDaata = new List<List<List<float>>>();//所有数据
List<List<string>> list_AllTime = new List<List<string>>();//所有时间
List<List<float>> liatAll = new List<List<float>>();//总数据汇总
List<string> list_Time = new List<string>();//时间
List<float> list_Tsi_Indoor_Data = new List<float>();//室内气溶胶浓度
List<float> list_Tsi_Outdoor_Data = new List<float>();//口罩内气溶胶浓度
List<float> lsit_XieLoulv = new List<float>();//泄露率
List<float> list_CO2_Indoor_Data = new List<float>();//室内CO2浓度
List<float> list_CO2_Outdoor_Data = new List<float>();//口罩内CO2浓度
List<float> list_O2_Data = new List<float>();//氧气浓度
List<float> list_HuanJingWenDu_Data = new List<float>();//环境内温度
List<float> list_HuanJingShiDu_Data = new List<float>();//环境湿度
// 修改timer_UpdataChart_Tick - 实时泄漏率计算
private void timer_UpdataChart_Tick(object sender, EventArgs e)
{
int currindex = 0;
if (isNeedRun)
{
currindex = 3;
}
else
{
currindex = 2;
}
if (data_M130_M135[1] && currentStepIndex >= currindex)
{
list_Time.Add(DateTime.Now.ToString("HH:mm:ss"));
list_Tsi_Indoor_Data.Add(experData.InDoor_TSINongDu);
list_Tsi_Outdoor_Data.Add(experData.Mask_TSINongDu);
// 使用最后100秒数据计算实时泄漏率
int dataCount = Math.Min(list_Tsi_Indoor_Data.Count, list_Tsi_Outdoor_Data.Count);
int startIndex = Math.Max(0, dataCount - 100);
List<float> last100Indoor = new List<float>();
List<float> last100Outdoor = new List<float>();
for (int i = startIndex; i < dataCount; i++)
{
last100Indoor.Add(list_Tsi_Indoor_Data[i]);
last100Outdoor.Add(list_Tsi_Outdoor_Data[i]);
}
if (last100Indoor.Count > 0 && last100Outdoor.Count > 0)
{
experData.XieLouLv = experData.ContinuousSamplingLeakageRate(
last100Indoor,
last100Outdoor,
experData.BenDiNongDu,
experData.SamplingFlowRate,
experData.DryingFlowRate);
}
lsit_XieLoulv.Add(experData.XieLouLv);
list_CO2_Indoor_Data.Add(experData.CO2NongDu_Indoor);
list_CO2_Outdoor_Data.Add(experData.Mask_CO2NongDu);
list_O2_Data.Add(experData.O2NongDu);
list_HuanJingWenDu_Data.Add(experData.HuanJingWenDu);
list_HuanJingShiDu_Data.Add(experData.HuanJingShiDu);
chart_TSI.Series[0].Points.DataBindXY(list_Time, list_Tsi_Indoor_Data);
chart_TSI.Series[1].Points.DataBindXY(list_Time, list_Tsi_Outdoor_Data);
chart_TSI.Series[2].Points.DataBindXY(list_Time, lsit_XieLoulv);
chart2.Series[0].Points.DataBindXY(list_Time, list_CO2_Indoor_Data);
chart2.Series[1].Points.DataBindXY(list_Time, list_CO2_Outdoor_Data);
chart2.Series[2].Points.DataBindXY(list_Time, list_O2_Data);
chart2.Series[3].Points.DataBindXY(list_Time, list_HuanJingWenDu_Data);
chart2.Series[4].Points.DataBindXY(list_Time, list_HuanJingShiDu_Data);
}
}
//结束时写入Excel
public static int comindex;
void bool_Stop_OnRisingEdge()
{
float xieLouLue_Agv = 0.0f;
int selectIndex = 0;
if (lsit_XieLoulv.Count != 0)
xieLouLue_Agv = lsit_XieLoulv.Average();
if (xieLouLue_Agv > experData.ExperMaskType)
{
form2.Invoke(new Action(() =>
{
form2.uiLabel1.Text = "测试失败!请等待指令重做实验!";
}));
MessageBox.Show("泄露率达到" + xieLouLue_Agv.ToString("F2") + "\n" + "不符合标准!请重做实验", "失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
// var result = MessageBox.Show("测试完成!" + "\n" + "是否保存数据?", "完成!", MessageBoxButtons.YesNo);
//如果点Yes则写入Excel
//如果点No则不写入Excel
List<string> _tempTimeList = new List<string>(list_Time);
List<float> _templist_Tsi_Indoor_Data = new List<float>(list_Tsi_Indoor_Data);
List<float> _templist_Tsi_Outdoor_Data = new List<float>(list_Tsi_Outdoor_Data);
List<float> _templsit_XieLoulv = new List<float>(lsit_XieLoulv);
List<float> _templist_CO2_Indoor_Data = new List<float>(list_CO2_Indoor_Data);
List<float> _templist_CO2_Outdoor_Data = new List<float>(list_CO2_Outdoor_Data);
List<float> _templist_O2_Data = new List<float>(list_O2_Data);
List<float> _templist_HuanJingWenDu_Data = new List<float>(list_HuanJingWenDu_Data);
List<float> _templist_HuanJingShiDu_Data = new List<float>(list_HuanJingShiDu_Data);
liatAll.Add(_templist_Tsi_Indoor_Data);
liatAll.Add(_templist_Tsi_Outdoor_Data);
liatAll.Add(_templsit_XieLoulv);
liatAll.Add(_templist_CO2_Indoor_Data);
liatAll.Add(_templist_CO2_Outdoor_Data);
liatAll.Add(_templist_O2_Data);
liatAll.Add(_templist_HuanJingWenDu_Data);
liatAll.Add(_templist_HuanJingShiDu_Data);
List<List<float>> _templiatAll = new List<List<float>>(liatAll);
list_AllDaata.Add(_templiatAll);
list_AllTime.Add(_tempTimeList);
//AddDgv();
this.Invoke(new Action(() =>
{
selectIndex = comboBox1.SelectedIndex;
}));
//if (selectIndex < stepList.Count - 1)
//{
// form2.Invoke(new Action(() =>
// {
// form2.uiLabel1.Text = "本次动作测试完成请等待10s后进行下一动作";
// }));
// Task.Delay(10000).Wait();
// this.Invoke(new Action(() =>
//{
// comboBox1.SelectedIndex += 1;
// experData.TestStatus = comboBox1.Text;
// btn_Start.PerformClick();
//}));
//}
//else
//{
// MessageBox.Show("所有动作测试完成!");
//}
}
}
#endregion
#region
// 修改btn_Start_Click - 加载配置参数
private void btn_Start_Click(object sender, EventArgs e)
{
string configPath = Path.Combine(Application.StartupPath, "UserData.json");
if (File.Exists(configPath))
{
var json = File.ReadAllText(configPath);
dynamic config = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
experData.BenDiNongDu = config.BenDiNongdu;
experData.SamplingFlowRate = config.SamplingFlowRate ?? 2.0f;
experData.DryingFlowRate = config.DryingFlowRate ?? 1.0f;
experData.ExperName = config.Category;
}
isPaused = false;
Pause1.Text = "暂停测试";
Pause1.Style = UIStyle.Red;
// 清空数据
list_Time.Clear();
list_Tsi_Indoor_Data.Clear();
list_Tsi_Outdoor_Data.Clear();
lsit_XieLoulv.Clear();
list_CO2_Indoor_Data.Clear();
list_CO2_Outdoor_Data.Clear();
list_O2_Data.Clear();
list_HuanJingWenDu_Data.Clear();
list_HuanJingShiDu_Data.Clear();
liatAll.Clear();
fc?.BtnClickFunction(Function.ButtonType., 130);
LoadIsNeedRunConfig();
InitStepList();
InitAutoStepTimer();
InitAutoStepTimer2();
StartProcess();
_logger.Log(loginData.UserName, "点击了【测试开始】按钮", loginData.UserPower.ToString());
}
private void btn_Stop_Click(object sender, EventArgs e)
{
isPaused = false;
Pause1.Text = "暂停测试";
Pause1.Style = UIStyle.Red;
form2.uiLabel1.Text = "测试停止";
fc?.BtnClickFunction(Function.ButtonType., 133);
master?.WriteSingleCoil(1, 16, false);
master?.WriteSingleCoil(1, 15, false);
form2.axWindowsMediaPlayer1.URL = string.Empty;
StopVideo();
autoStepTimer?.Stop();
autoStepTimer2?.Stop();
lb_status.Text = "测试停止";
_logger.Log(loginData.UserName, "点击了【测试停止】按钮", loginData.UserPower.ToString());
}
//private void btn_SaveData_Click(object sender, EventArgs e)
//{
// experExcleHelper.ExportToExcel(dt_Show, list_AllTime, list_AllDaata);
// _logger.Log(loginData.UserName, "导出了实验数据", loginData.UserPower.ToString());
//}
// 修正后的按钮点击事件
private void btn_SaveData_Click(object sender, EventArgs e)
{
// 使用支持按钮选择的重载方法message, title, style, buttons
bool isYes = Sunny.UI.UIMessageBox.Show(
"选择导出类型:\n确定 - 本次实验\n取消 - 历史实验",
"导出选择",
Sunny.UI.UIStyle.Blue, // 使用指定样式
Sunny.UI.UIMessageBoxButtons.OKCancel // 明确指定按钮类型
);
if (isYes) // 注意此重载返回bool值true表示Yesfalse表示No
{
ExportLastExperimentToExcel();
}
else
{
ExportSelectedHistoricalExperiments();
}
_logger.Log(loginData.UserName, "导出了实验数据", loginData.UserPower.ToString());
}
private void ExportLastExperimentToExcel()
{
string dbPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data.db");
using (var db = new SQLiteConnection(dbPath))
{
try
{
var latestRecord = db.Table<Experiment>()
.Where(x => x.IdNumber != null && x.IdNumber != ""
&& x.Date != null && x.Date != ""
&& x.Time != null && x.Time != "")
.OrderByDescending(x => x.Date)
.ThenByDescending(x => x.Time)
.FirstOrDefault();
if (latestRecord == null || string.IsNullOrEmpty(latestRecord.IdNumber))
{
UIMessageBox.Show("没有找到有效的实验数据!", "提示", Sunny.UI.UIStyle.Blue);
return;
}
string targetIdNumber = latestRecord.IdNumber;
string targetName = latestRecord.Name ?? "未知姓名";
var latestRecordid = latestRecord.Id;
var startindex = latestRecordid - 5;
var experimentRecords = db.Table<Experiment>()
.Where(x => x.IdNumber == targetIdNumber && x.Id > startindex)
.OrderBy(x => x.Date)
.ThenBy(x => x.Time)
.ToList();
if (experimentRecords.Count == 0)
{
UIMessageBox.Show($"未找到身份证号{targetIdNumber}的实验数据!", "提示", Sunny.UI.UIStyle.Blue);
return;
}
using (var package = new ExcelPackage())
{
var worksheet = package.Workbook.Worksheets.Add($"[{targetName}]{targetIdNumber}_实验数据");
string maskType = experimentRecords.Max(f => f.MaskType);
string maskTypeName = string.Empty;
if (maskType != null && (maskType.Contains("半面罩") || maskType.Contains("全面罩")))
{
maskTypeName = "IL";
}
else if (maskType != null && (maskType.Contains("随弃式")))
{
maskTypeName = "TIL";
}
maskTypeName = $"泄漏率{maskTypeName}(%)";
// 中文表头映射
var chineseHeaders = new Dictionary<string, string>
{
{ "Name", "姓名" },
{ "Sex", "性别" },
{ "Age", "年龄" },
{ "IdNumber", "身份证号码" },
{ "Company", "工作单位" },
{ "CompanyAge", "工龄" },
{ "Date", "日期" },
{ "Time", "时间" },
{ "ExperName", "实验员" },
{ "ExperType", "样品类别" },
{ "MaskType", "面罩类型" },
{ "TestStatus", "测试状态" },
{ "HuanJingWenDu", "环境温度(℃)" },
{ "HuanJingShiDu", "环境湿度(%RH)" },
{ "BenDiNongDu", "本底浓度(mg/m³)" },
{ "TsiIndoorAgv", "室内浓度平均值(mg/m³)" },
{ "TsiOutdoorAgv", "呼吸器内气溶胶平均浓度(mg/m³)" },
{ "Xieloulv", $"{maskTypeName}" },
{ "TotalXieloulv", "总泄漏率(%)" },
{ "OverallTotalXieloulv", "总体总泄漏率(%)" } // 新增总体总泄露率表头
};
var properties = typeof(Experiment).GetProperties().ToList();
// 计算5个动作的泄露率平均值过滤无效的0值
var validXieloulvList = experimentRecords
.Where(r => r.Xieloulv > 0) // 排除泄露率为0的无效数据
.Select(r => r.Xieloulv)
.ToList();
var totalXieloulv = validXieloulvList.Any()
? validXieloulvList.Average()
: 0;
// === 新增计算总体总泄露率5个动作的平均值===
var fiveActionRecords = experimentRecords
.Where(r => r.Xieloulv > 0) // 过滤有效数据
.Take(5) // 取前5个动作
.ToList();
var overallTotalXieloulv = fiveActionRecords.Any()
? fiveActionRecords.Average(r => r.Xieloulv)
: 0;
// === 新增结束 ===
// 写入中文表头
int colIndex = 1;
foreach (var prop in properties)
{
worksheet.Cells[1, colIndex].Value = chineseHeaders.ContainsKey(prop.Name)
? chineseHeaders[prop.Name]
: prop.Name;
worksheet.Cells[1, colIndex].Style.Font.Bold = true;
colIndex++;
}
// 单独写入"总泄漏率(%)"表头
worksheet.Cells[1, colIndex].Value = chineseHeaders["TotalXieloulv"];
worksheet.Cells[1, colIndex].Style.Font.Bold = true;
colIndex++;
// 单独写入"总体总泄漏率(%)"表头
worksheet.Cells[1, colIndex].Value = chineseHeaders["OverallTotalXieloulv"];
worksheet.Cells[1, colIndex].Style.Font.Bold = true;
// 写入数据行
int rowIndex = 2;
foreach (var record in experimentRecords)
{
colIndex = 1;
// 写入原有数据列
foreach (var prop in properties)
{
if (prop.Name == "ExperNum")
{
continue;
}
worksheet.Cells[rowIndex, colIndex].Value = prop.GetValue(record);
if (prop.PropertyType == typeof(float) || prop.PropertyType == typeof(double))
{
worksheet.Cells[rowIndex, colIndex].Style.Numberformat.Format = "0.00";
}
colIndex++;
}
// 写入总泄漏率(每行都写入)
worksheet.Cells[rowIndex, colIndex].Value = record.Xieloulv;
worksheet.Cells[rowIndex, colIndex].Style.Numberformat.Format = "0.00";
colIndex++;
// 写入总体总泄漏率(仅在最后一行显示)
if (rowIndex == experimentRecords.Count + 1)
{
worksheet.Cells[rowIndex, colIndex].Value = overallTotalXieloulv;
worksheet.Cells[rowIndex, colIndex].Style.Numberformat.Format = "0.00";
// 给总体总泄露率行添加背景色,方便识别
worksheet.Cells[rowIndex, colIndex].Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
worksheet.Cells[rowIndex, colIndex].Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightBlue);
}
rowIndex++;
}
// 调整列宽
worksheet.Column(13).Width = 25; // 环境温度(℃)
worksheet.Column(14).Width = 25; // 环境湿度(%RH)
worksheet.Column(15).Width = 20; // 本底浓度(mg/m³)
worksheet.Column(16).Width = 25; // 室内浓度平均值(mg/m³)
worksheet.Column(17).Width = 25; // 口罩内浓度平均值(mg/m³)
worksheet.Column(18).Width = 25; // 泄漏率IL/TIL(%)
worksheet.Column(19).Width = 25; // 总泄漏率(%)
worksheet.Column(20).Width = 25; // 总体总泄漏率(%)(新增列)
SaveExcelFile(package, $"[{targetName}]的实验数据(共{experimentRecords.Count}条,总泄露率:{totalXieloulv:F2}%,总体总泄露率:{overallTotalXieloulv:F2}%)导出成功!", $"[{targetName}]{targetIdNumber}_实验数据");
}
}
catch (Exception ex)
{
UIMessageBox.Show($"导出失败: {ex.Message}", "错误", Sunny.UI.UIStyle.Blue);
}
}
}
private void ExportSelectedHistoricalExperiments()
{
string dbPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data.db");
using (var db = new SQLiteConnection(dbPath))
{
try
{
var personList = db.Table<Experiment>()
.Where(x => x.IdNumber != null && x.IdNumber != ""
&& x.Name != null && x.Name != "")
.Select(x => new { x.IdNumber, x.Name, x.Date, x.Time, x.Id, x.MaskType })
.OrderByDescending(x => x.Id).ThenByDescending(s => s.Date).ThenByDescending(s => s.Time)
.ToList();
if (personList == null || personList.Count == 0)
{
UIMessageBox.Show("没有找到历史实验数据!", "提示", Sunny.UI.UIStyle.Blue);
return;
}
string maskType = personList.Max(f => f.MaskType);
string maskTypeName = string.Empty;
if (maskType != null && (maskType.Contains("半面罩") || maskType.Contains("全面罩")))
{
maskTypeName = "IL";
}
else if (maskType != null && (maskType.Contains("随弃式")))
{
maskTypeName = "TIL";
}
maskTypeName = $"泄漏率{maskTypeName}(%)";
var displayList = personList.Select(p =>
{
string idLast4 = p.IdNumber;
return $"({p.Id})({p.Date} {p.Time})({p.Name}){idLast4}";
}).ToList();
var selectForm = new UISelectForm("选择要导出的人员", displayList);
if (selectForm.ShowDialog() == DialogResult.OK && selectForm.SelectedItems.Count > 0)
{
var selectedIds = new List<string>();
foreach (var selectedItem in selectForm.SelectedItems)
{
var itemStr = selectedItem.ToString();
var first = itemStr.IndexOf("(") + 1;
var second = itemStr.IndexOf(")");
var nameStart = itemStr.LastIndexOf("(") + 1;
var nameEnd = itemStr.LastIndexOf(")");
var idStart = itemStr.LastIndexOf("") + 1;
var idEnd = itemStr.LastIndexOf("");
if (nameStart < nameEnd && idStart < idEnd)
{
var id = itemStr.Substring(first, second - first);
var name = itemStr.Substring(nameStart, nameEnd - nameStart);
var idNumber = itemStr.Substring(idStart, idEnd - idStart);
var match = personList.FirstOrDefault(p =>
p.Name == name && p.IdNumber == idNumber);
//if (match != null && !selectedIds.Contains(match.IdNumber))
//{
selectedIds.Add(id.ToString());
//}
}
}
if (selectedIds.Count == 0)
{
UIMessageBox.Show("未匹配到有效人员数据!", "提示", Sunny.UI.UIStyle.Blue);
return;
}
using (var package = new ExcelPackage())
{
var worksheet = package.Workbook.Worksheets.Add($"选中的{selectedIds.Count / 5}位人员实验数据!");
// 中文表头映射(保持不变)
var chineseHeaders = new Dictionary<string, string>
{
{ "Name", "姓名" },
{ "Sex", "性别" },
{ "Age", "年龄" },
{ "IdNumber", "身份证号码" },
{ "Company", "工作单位" },
{ "CompanyAge", "工龄" },
{ "Date", "日期" },
{ "Time", "时间" },
{ "ExperName", "实验员" },
{ "ExperType", "样品类别" },
{ "MaskType", "面罩类型" },
{ "TestStatus", "测试状态" },
{ "HuanJingWenDu", "环境温度(℃)" },
{ "HuanJingShiDu", "环境湿度(%RH)" },
{ "BenDiNongDu", "本底浓度(mg/m³)" },
{ "TsiIndoorAgv", "室内浓度平均值(mg/m³)" },
{ "TsiOutdoorAgv", "呼吸器内气溶胶平均浓度(mg/m³)" },
{ "Xieloulv", $"{maskTypeName}" },
{ "TotalXieloulv", "总体总泄漏率(%)" }
};
var properties = typeof(Experiment).GetProperties().ToList();
var hiddenColumns = new List<string> { "Sex", "Age", "Company", "CompanyAge" };
var visibleProperties = properties.Where(p => !hiddenColumns.Contains(p.Name)).ToList();
// 1. 写入中文表头(保持不变)
int colIndex = 1;
foreach (var prop in visibleProperties)
{
worksheet.Cells[1, colIndex].Value = chineseHeaders.ContainsKey(prop.Name)
? chineseHeaders[prop.Name]
: prop.Name;
worksheet.Cells[1, colIndex].Style.Font.Bold = true;
colIndex++;
}
// 单独写入"总泄露率"表头(最后一列)
worksheet.Cells[1, colIndex].Value = chineseHeaders["TotalXieloulv"];
worksheet.Cells[1, colIndex].Style.Font.Bold = true;
var totalColIndex = colIndex;
// 2. 按人员写入数据,并计算每人的总泄露率(保持不变)
int rowIndex = 2;
var allActionLeakRates = new List<float>(); // 存储所有动作的泄露率
var allPersonTotalLeakRates = new List<float>(); // 存储所有人的总泄露率
List<int> ids = selectedIds.ConvertAll(int.Parse);
var lsit = db.Table<Experiment>()
.Where(x => ids.Contains(x.Id))
.OrderBy(x => x.Date)
.ThenBy(x => x.Time)
.ToList();
var selidNumber = lsit.Select(x => x.IdNumber).Distinct().ToList();
foreach (var id in selidNumber)
{
var personExperiments = lsit
.Where(x => x.IdNumber == id)
.OrderBy(x => x.Date)
.ThenBy(x => x.Time)
.ToList();
if (!personExperiments.Any()) continue;
// 计算当前人员的总泄露率过滤无效的0值
var validLeakRates = personExperiments
.Where(exp => exp.Xieloulv > 0)
.Select(exp => exp.Xieloulv)
.ToList();
var personTotalLeakRate = validLeakRates.Any()
? validLeakRates.Average()
: 0;
// 收集所有动作泄露率和人员总泄露率
allActionLeakRates.AddRange(validLeakRates);
allPersonTotalLeakRates.Add(personTotalLeakRate);
// 写入当前人员的每条实验记录(保持不变)
foreach (var exp in personExperiments)
{
colIndex = 1;
foreach (var prop in visibleProperties)
{
if (prop.Name == "ExperNum") continue;
worksheet.Cells[rowIndex, colIndex].Value = prop.GetValue(exp);
if (prop.PropertyType == typeof(float) || prop.PropertyType == typeof(double))
{
worksheet.Cells[rowIndex, colIndex].Style.Numberformat.Format = "0.00";
}
colIndex++;
}
worksheet.Cells[rowIndex, totalColIndex].Value = "";
rowIndex++;
}
// 3. 在当前人员数据末尾添加"总泄露率"汇总行(保持不变)
colIndex = 1;
worksheet.Cells[rowIndex, 1].Value = $"{personExperiments[0].Name}(汇总)";
worksheet.Cells[rowIndex, 1, rowIndex, visibleProperties.Count].Merge = true;
worksheet.Cells[rowIndex, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
worksheet.Cells[rowIndex, totalColIndex].Value = personTotalLeakRate;
worksheet.Cells[rowIndex, totalColIndex].Style.Numberformat.Format = "0.00";
worksheet.Cells[rowIndex, 1, rowIndex, totalColIndex].Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
worksheet.Cells[rowIndex, 1, rowIndex, totalColIndex].Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightSkyBlue);
rowIndex++;
// 人员之间添加空行
rowIndex++;
}
// 4. 在表格最下方添加统计行(新增部分)
if (selectedIds.Count > 0)
{
//// 获取主要口罩类型(假设同一组使用相同类型的口罩)
//string mainMaskType = db.Table<Experiment>()
// .Where(x => selectedIds.Contains(x.Id))
// .Select(x => x.MaskType)
// .FirstOrDefault() ?? "";
var (actionStandard, personStandard) = GetMaskTypeStandards(maskType);
// 50个动作合格性统计
var validActions = allActionLeakRates.Where(r => r > 0).Take(50).ToList();
int qualifiedActionCount = validActions.Count(r => r <= actionStandard);
bool isActionsQualified = validActions.Count >= 50 && qualifiedActionCount >= 46;
// 10人总体合格性统计
var validPersons = allPersonTotalLeakRates.Take(10).ToList();
int qualifiedPersonCount = validPersons.Count(r => r <= personStandard);
bool isPersonsQualified = validPersons.Count >= 10 && qualifiedPersonCount >= 8;
// 添加50个动作合格性统计行
colIndex = 1;
worksheet.Cells[rowIndex, 1].Value = "50个动作是否合格";
worksheet.Cells[rowIndex, 1, rowIndex, visibleProperties.Count].Merge = true;
worksheet.Cells[rowIndex, 1].Style.Font.Bold = true;
string actionResult = isActionsQualified ? "合格" : "不合格";
if (selectedIds.Count < 50)
{
actionResult = $"数据不足({validActions.Count}/50个动作";
}
else
{
actionResult = $"{actionResult}{qualifiedActionCount}/50个动作";
}
worksheet.Cells[rowIndex, totalColIndex].Value = actionResult;
worksheet.Cells[rowIndex, totalColIndex].Style.Font.Color.SetColor(
isActionsQualified ? System.Drawing.Color.Green : System.Drawing.Color.Red);
worksheet.Cells[rowIndex, 1, rowIndex, totalColIndex].Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
worksheet.Cells[rowIndex, 1, rowIndex, totalColIndex].Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightYellow);
rowIndex++;
// 添加10人总体合格性统计行
colIndex = 1;
worksheet.Cells[rowIndex, 1].Value = "10人总体是否合格";
worksheet.Cells[rowIndex, 1, rowIndex, visibleProperties.Count].Merge = true;
worksheet.Cells[rowIndex, 1].Style.Font.Bold = true;
string personResult = isPersonsQualified ? "合格" : "不合格";
if (validPersons.Count < 10)
{
personResult = $"数据不足({validPersons.Count}/10人";
}
else
{
personResult = $"{personResult}{qualifiedPersonCount}/10人";
}
worksheet.Cells[rowIndex, totalColIndex].Value = personResult;
worksheet.Cells[rowIndex, totalColIndex].Style.Font.Color.SetColor(
isPersonsQualified ? System.Drawing.Color.Green : System.Drawing.Color.Red);
worksheet.Cells[rowIndex, 1, rowIndex, totalColIndex].Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
worksheet.Cells[rowIndex, 1, rowIndex, totalColIndex].Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightYellow);
}
// 5. 调整列宽(保持不变)
worksheet.Column(7).Width = 25;
worksheet.Column(8).Width = 25;
worksheet.Column(9).Width = 20;
worksheet.Column(10).Width = 25;
worksheet.Column(11).Width = 25;
worksheet.Column(12).Width = 25;
worksheet.Column(totalColIndex).Width = 25;
SaveExcelFile(package, $"选中的{selectedIds.Count / 5}位人员实验数据导出成功!", $"选中的{selectedIds.Count / 5}位人员实验数据");
}
}
}
catch (Exception ex)
{
UIMessageBox.Show($"导出失败: {ex.Message}", "错误", Sunny.UI.UIStyle.Blue);
}
}
}
// 新增辅助方法:根据口罩类型获取标准值
private (float actionStandard, float personStandard) GetMaskTypeStandards(string maskType)
{
if (string.IsNullOrEmpty(maskType)) return (0, 0);
if (maskType.Contains("KN90") || maskType.Contains("KP90"))
{
return (13.0f, 10.0f);
}
else if (maskType.Contains("KN95") || maskType.Contains("KP95"))
{
return (11.0f, 8.0f);
}
else if (maskType.Contains("KN100") || maskType.Contains("KP100"))
{
return (5.0f, 2.0f);
}
else
{
return (0, 0);
}
}
/// <summary>
/// 保存Excel文件的通用方法
/// </summary>
private void SaveExcelFile(ExcelPackage package, string successMessage, string fileName)
{
SaveFileDialog saveFileDialog = new SaveFileDialog
{
Filter = "Excel Files|*.xlsx",
Title = "保存实验数据",
FileName = $"{fileName}_{DateTime.Now:yyyyMMddHHmmss}.xlsx"
};
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
try
{
FileInfo fileInfo = new FileInfo(saveFileDialog.FileName);
package.SaveAs(fileInfo);
// 成功提示(带标题)
UIMessageBox.Show(successMessage, "成功", Sunny.UI.UIStyle.Blue);
}
catch (Exception ex)
{
// 错误提示
UIMessageBox.Show($"保存文件失败: {ex.Message}", "错误", Sunny.UI.UIStyle.Blue);
}
}
}
// 人员选择对话框(保持样式一致)
//public class UISelectForm : Sunny.UI.UIForm
//{
// private Sunny.UI.UIListBox listBox;
// private Sunny.UI.UIButton okButton;
// private Sunny.UI.UIButton cancelButton;
// public List<object> SelectedItems => listBox.SelectedItems.Cast<object>().ToList();
// public UISelectForm(string title, List<string> items)
// {
// Text = title;
// Width = 600;
// Height = 500;
// StartPosition = FormStartPosition.CenterParent;
// Style = Sunny.UI.UIStyle.Blue; // 匹配主窗体样式
// // 初始化列表框
// listBox = new Sunny.UI.UIListBox
// {
// Dock = DockStyle.Top,
// Height = 400,
// SelectionMode = SelectionMode.MultiSimple,
// Style = this.Style
// };
// listBox.Items.AddRange(items.ToArray());
// // 初始化按钮
// okButton = new Sunny.UI.UIButton
// {
// Text = "确定",
// Dock = DockStyle.Left,
// Width = 100,
// Style = this.Style
// };
// okButton.Click += (s, e) =>
// {
// DialogResult = DialogResult.OK;
// Close();
// };
// cancelButton = new Sunny.UI.UIButton
// {
// Text = "取消",
// Dock = DockStyle.Right,
// Width = 100,
// Style = this.Style
// };
// cancelButton.Click += (s, e) =>
// {
// DialogResult = DialogResult.Cancel;
// Close();
// };
// // 创建按钮容器
// var buttonPanel = new Panel
// {
// Dock = DockStyle.Bottom,
// Height = 50,
// BackColor = System.Drawing.Color.Transparent
// };
// buttonPanel.Controls.Add(okButton);
// buttonPanel.Controls.Add(cancelButton);
// Controls.Add(listBox);
// Controls.Add(buttonPanel);
// }
//}
public class UISelectForm : UIForm
{
private UIListBox listBox;
private UIButton okButton;
private UIButton cancelButton;
private UIButton queryButton;
private UIDatePicker startDatePicker;
private UIDatePicker endDatePicker;
private UILabel startDateLabel;
private UILabel endDateLabel;
// 原始数据源保存所有未过滤的item用于重置
private List<string> _originalItems;
// 选中项集合(保持原有逻辑)
public List<object> SelectedItems => listBox.SelectedItems.Cast<object>().ToList();
public UISelectForm(string title, List<string> items)
{
// 保存原始数据源
_originalItems = new List<string>(items);
// 基础窗体设置
Text = title;
Width = 800; // 加宽窗体以容纳日期控件
Height = 550;
StartPosition = FormStartPosition.CenterParent;
Style = UIStyle.Blue;
// 初始化日期筛选控件
InitDateFilterControls();
// 初始化列表框
InitListBox();
// 初始化按钮(确定/取消/查询)
InitButtons();
// 组装控件布局
AssembleControls();
}
/// <summary>
/// 初始化日期筛选控件(标签+日期选择器)
/// </summary>
private void InitDateFilterControls()
{
// 开始日期标签
startDateLabel = new UILabel
{
Text = "开始日期:",
Size = new Size(80, 30),
TextAlign = ContentAlignment.MiddleRight,
Style = this.Style
};
// 开始日期选择器
startDatePicker = new UIDatePicker
{
Size = new Size(200, 30),
DateFormat = "yyyy-MM-dd HH:mm:ss", // 短日期格式yyyy-MM-dd
Value = DateTime.Now.AddDays(-7), // 默认筛选近7天数据
Style = this.Style
};
// 结束日期标签
endDateLabel = new UILabel
{
Text = "结束日期:",
Size = new Size(80, 30),
TextAlign = ContentAlignment.MiddleRight,
Style = this.Style
};
// 结束日期选择器
endDatePicker = new UIDatePicker
{
Size = new Size(200, 30),
DateFormat = "yyyy-MM-dd HH:mm:ss", // 短日期格式yyyy-MM-dd
Value = DateTime.Now, // 默认结束日期为今天
Style = this.Style
};
// 查询按钮
queryButton = new UIButton
{
Text = "查询",
Size = new Size(100, 30),
Style = this.Style
};
// 绑定查询事件
queryButton.Click += QueryButton_Click;
}
/// <summary>
/// 初始化列表框(保持原有逻辑)
/// </summary>
private void InitListBox()
{
listBox = new UIListBox
{
Dock = DockStyle.Top,
Height = 400,
SelectionMode = SelectionMode.MultiSimple,
Style = this.Style
};
// 初始加载所有原始数据
listBox.Items.AddRange(_originalItems.ToArray());
}
/// <summary>
/// 初始化按钮(确定/取消)
/// </summary>
private void InitButtons()
{
okButton = new UIButton
{
Text = "确定",
Dock = DockStyle.Left,
Width = 100,
Style = this.Style
};
okButton.Click += (s, e) =>
{
DialogResult = DialogResult.OK;
Close();
};
cancelButton = new UIButton
{
Text = "取消",
Dock = DockStyle.Right,
Width = 100,
Style = this.Style
};
cancelButton.Click += (s, e) =>
{
DialogResult = DialogResult.Cancel;
Close();
};
}
/// <summary>
/// 组装所有控件到窗体
/// </summary>
private void AssembleControls()
{
// 日期筛选面板(横向排列日期控件和查询按钮)
var filterPanel = new Panel
{
Dock = DockStyle.Top,
Height = 40,
BackColor = Color.Transparent
};
// 添加日期控件到筛选面板(设置位置,避免重叠)
filterPanel.Controls.Add(startDateLabel);
startDateLabel.Location = new Point(20, 5);
filterPanel.Controls.Add(startDatePicker);
startDatePicker.Location = new Point(100, 5);
filterPanel.Controls.Add(endDateLabel);
endDateLabel.Location = new Point(320, 5);
filterPanel.Controls.Add(endDatePicker);
endDatePicker.Location = new Point(400, 5);
filterPanel.Controls.Add(queryButton);
queryButton.Location = new Point(620, 5);
// 按钮面板(确定/取消)
var buttonPanel = new Panel
{
Dock = DockStyle.Bottom,
Height = 50,
BackColor = Color.Transparent
};
buttonPanel.Controls.Add(okButton);
buttonPanel.Controls.Add(cancelButton);
// 把控件添加到窗体
Controls.Add(filterPanel); // 筛选面板在最顶部
Controls.Add(listBox); // 列表框在中间
Controls.Add(buttonPanel); // 按钮面板在底部
}
/// <summary>
/// 查询按钮点击事件:根据日期筛选列表数据
/// </summary>
private void QueryButton_Click(object sender, EventArgs e)
{
// 获取筛选条件(只取日期部分,忽略时间)
DateTime startDate = startDatePicker.Value.Date;
DateTime endDate = endDatePicker.Value.Date;
// 校验日期逻辑(开始日期不能晚于结束日期)
if (startDate > endDate)
{
UIMessageBox.Show("开始日期不能晚于结束日期!", "提示", UIStyle.Blue, UIMessageBoxButtons.OK);
return;
}
// 清空现有列表
listBox.Items.Clear();
// 遍历原始数据筛选符合日期条件的item
foreach (var item in _originalItems)
{
// 解析item中的日期字符串
if (TryExtractDateFromItem(item, out DateTime itemDate))
{
// 判断item日期是否在筛选范围内包含开始和结束日期
if (itemDate.Date >= startDate && itemDate.Date <= endDate)
{
listBox.Items.Add(item);
}
}
else
{
// 无法解析日期的item可选择忽略或保留这里默认保留避免数据丢失
listBox.Items.Add(item);
// 可选:输出日志提示格式异常
// Console.WriteLine($"警告item格式异常无法解析日期 - {item}");
}
}
// 提示筛选结果
UIMessageBox.Show($"筛选完成!共找到 {listBox.Items.Count} 条符合条件的数据", "提示", UIStyle.Blue, UIMessageBoxButtons.OK);
}
private bool TryExtractDateFromItem(string item, out DateTime itemDate)
{
itemDate = DateTime.MinValue;
try
{
// 步骤1按括号分割字符串处理中英文括号修正Split参数先指定分隔符数组再指定StringSplitOptions
char[] separators = new[] { '(', ')' };
var parts = item.Split(separators, StringSplitOptions.RemoveEmptyEntries);
// 步骤2取第二个有效部分索引1即日期字符串格式2025-11-25 15-42-04
if (parts.Length < 2) return false;
string dateStr = parts[1].Trim();
// 步骤3只替换时间部分的"-"为":"(保留日期部分的"-"
if (dateStr.Contains(" "))
{
var dateTimeParts = dateStr.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (dateTimeParts.Length == 2)
{
string datePart = dateTimeParts[0]; // 日期部分2025-11-25保留"-"
string timePart = dateTimeParts[1]; // 时间部分15-42-04替换"-"为":"
timePart = timePart.Replace("-", ":"); // 转换为15:42:04
dateStr = $"{datePart} {timePart}"; // 重组为标准格式2025-11-25 15:42:04
}
}
// 步骤4解析标准日期时间格式
return DateTime.TryParse(dateStr, out itemDate);
}
catch (Exception ex)
{
Console.WriteLine($"解析item日期失败{ex.Message} - {item}");
return false;
}
}
}
private void ExportCurrentExperimentToExcel(DataTable dataTable, List<List<string>> stringData, List<List<List<float>>> floatData)
{
using (var package = new ExcelPackage())
{
var worksheet = package.Workbook.Worksheets.Add("Current Experiment");
// 写入数据(不包括姓名、性别、年龄、身份证号码、工作单位、工龄)
string[] headers = {
"时间", "室内气溶胶浓度", "口罩内气溶胶浓度", "泄露率",
"室内CO2浓度", "口罩内CO2浓度", "室内氧浓度", "室内温度", "室内湿度"
};
for (int col = 0; col < headers.Length; col++)
{
worksheet.Cells[1, col + 1].Value = headers[col];
}
for (int sheetIndex = 0; sheetIndex < stringData.Count; sheetIndex++)
{
List<string> currentStringData = stringData[sheetIndex];
List<List<float>> currentFloatData = floatData[sheetIndex];
for (int row = 0; row < currentStringData.Count; row++)
{
worksheet.Cells[row + 2, 1].Value = currentStringData[row];
}
for (int col = 0; col < currentFloatData.Count; col++)
{
List<float> columnData = currentFloatData[col];
for (int row = 0; row < columnData.Count; row++)
{
worksheet.Cells[row + 2, col + 2].Value = columnData[row];
}
}
}
SaveExcelFile(package);
}
}
private void ExportHistoricalExperimentToExcel()
{
// 从数据库读取历史实验数据
List<string> names = GetNamesFromDatabase();
using (var package = new ExcelPackage())
{
foreach (var name in names)
{
var worksheet = package.Workbook.Worksheets.Add(name);
// 从数据库获取该姓名的实验数据
DataTable dataTable = GetExperimentDataByName(name);
// 写入数据
for (int col = 0; col < dataTable.Columns.Count; col++)
{
worksheet.Cells[1, col + 1].Value = dataTable.Columns[col].ColumnName;
}
for (int row = 0; row < dataTable.Rows.Count; row++)
{
for (int col = 0; col < dataTable.Columns.Count; col++)
{
worksheet.Cells[row + 2, col + 1].Value = dataTable.Rows[row][col];
}
}
}
SaveExcelFile(package);
}
}
private void SaveExcelFile(ExcelPackage package)
{
SaveFileDialog saveFileDialog = new SaveFileDialog
{
Filter = "Excel Files|*.xlsx",
Title = "保存 Excel 文件"
};
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
FileInfo fileInfo = new FileInfo(saveFileDialog.FileName);
package.SaveAs(fileInfo);
MessageBox.Show("数据导出成功!");
}
}
private List<string> GetNamesFromDatabase()
{
// 从数据库获取所有姓名
// 示例代码,需根据实际数据库结构实现
return new List<string> { "姓名1", "姓名2" };
}
private DataTable GetExperimentDataByName(string name)
{
// 从数据库获取指定姓名的实验数据
// 示例代码,需根据实际数据库结构实现
return new DataTable();
}
#endregion
private void btn_ClearData_Click(object sender, EventArgs e)
{
dt_Show.Clear();
list_Time.Clear();
list_Tsi_Indoor_Data.Clear();
list_Tsi_Outdoor_Data.Clear();
//experData.XieLouLv = experData.CumulativeLeakageRate(list_Tsi_Indoor_Data, list_Tsi_Outdoor_Data, experData.BenDiNongDu, 1.0f);
lsit_XieLoulv.Clear();
list_CO2_Indoor_Data.Clear();
list_CO2_Outdoor_Data.Clear();
list_O2_Data.Clear();
list_HuanJingWenDu_Data.Clear();
list_HuanJingShiDu_Data.Clear();
liatAll.Clear();
list_AllTime.Clear();
_logger.Log(loginData.UserName, "点击了【数据清除】按钮", loginData.UserPower.ToString());
}
private void btn_Next_Click(object sender, EventArgs e)
{
GoToNextStep();
_logger.Log(loginData.UserName, "进入流程", loginData.UserPower.ToString());
}
private void Pause_Click(object sender, EventArgs e)
{
try
{
if (!isPaused)
{
// 暂停操作
PauseTest();
master?.WriteSingleCoil(1, 40, true);
}
else
{
// 继续操作
ResumeTest();
master?.WriteSingleCoil(1, 40, false);
}
_logger.Log(loginData.UserName,
isPaused ? "点击了【暂停】按钮" : "点击了【继续】按钮",
loginData.UserPower.ToString());
}
catch (Exception ex)
{
MessageBox.Show($"暂停/继续操作失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
_logger.Log(loginData.UserName, $"暂停/继续操作失败: {ex.Message}", loginData.UserPower.ToString());
}
}
/// <summary>
/// 暂停测试
/// </summary>
private void PauseTest()
{
// 停止自动步骤计时器
autoStepTimer?.Stop();
// 保存剩余的秒数
pausedRemainingSeconds = countdownSeconds;
// 暂停视频播放
if (form2.axWindowsMediaPlayer1.playState == WMPLib.WMPPlayState.wmppsPlaying)
{
form2.axWindowsMediaPlayer1.Ctlcontrols.pause();
// 保存当前视频路径以便恢复时使用
currentVideoPath = form2.axWindowsMediaPlayer1.URL;
}
// 更新界面状态
lb_status.Text = $"{stepList[currentStepIndex]} - 已暂停 (剩余: {pausedRemainingSeconds}秒)";
//form2.uiLabel1.Text = $"{form2.uiLabel1.Text.Replace("倒计时:", "已暂停 - 剩余: ")}";
// 更新按钮文本和颜色
Pause1.Text = "继续测试";
Pause1.Style = UIStyle.Green; // 使用绿色表示继续
// 禁用其他控制按钮(可选)
//btn_Start.Enabled = false;
//btn_Stop.Enabled = false;
//btn_NextStep.Enabled = false;
isPaused = true;
// 记录暂停日志
_logger.Log(loginData.UserName,
$"测试暂停 - 步骤[{currentStepIndex + 1}]: {stepList[currentStepIndex]}, 剩余时间: {pausedRemainingSeconds}秒",
loginData.UserPower.ToString());
}
/// <summary>
/// 继续测试
/// </summary>
private void ResumeTest()
{
// 恢复倒计时秒数
countdownSeconds = pausedRemainingSeconds;
// 恢复视频播放
if (!string.IsNullOrEmpty(currentVideoPath) && File.Exists(currentVideoPath))
{
// 如果视频路径有效,恢复播放
form2.axWindowsMediaPlayer1.Ctlcontrols.play();
}
else if (form2.axWindowsMediaPlayer1.URL != null &&
File.Exists(form2.axWindowsMediaPlayer1.URL))
{
// 如果当前有视频在加载,也尝试恢复
form2.axWindowsMediaPlayer1.Ctlcontrols.play();
}
// 重新启动计时器
autoStepTimer?.Start();
// 更新界面状态
lb_status.Text = $"{stepList[currentStepIndex]} 倒计时: {countdownSeconds}秒";
//// 更新form2的标签文本移除暂停提示
//int index = form2.uiLabel1.Text.LastIndexOf("\r\n[已暂停");
//if (index > 0)
//{
// form2.uiLabel1.Text = form2.uiLabel1.Text.Substring(0, index) + $"\r\n倒计时: {countdownSeconds}秒";
//}
//else
//{
// form2.uiLabel1.Text = form2.uiLabel1.Text.Replace("[已暂停]", "") + $"\r\n倒计时: {countdownSeconds}秒";
//}
// 更新按钮文本和颜色
Pause1.Text = "暂停测试";
Pause1.Style = UIStyle.Red; // 使用红色表示暂停
//// 启用其他控制按钮
//btn_Start.Enabled = true;
//btn_Stop.Enabled = true;
btn_NextStep.Enabled = true;
isPaused = false;
// 记录继续日志
_logger.Log(loginData.UserName,
$"测试继续 - 步骤[{currentStepIndex + 1}]: {stepList[currentStepIndex]}, 剩余时间: {countdownSeconds}秒",
loginData.UserPower.ToString());
}
}
}