Files
kou_zhaoxielou_shandong/口罩泄露定制款/Form/frm_Main.cs

2354 lines
98 KiB
C#
Raw Normal View History

2026-01-16 20:53:33 +08:00
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;
}
}
}
// 3. 步骤初始化
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)
{
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();
// 关键修改:使用与 timer_UpdataChart_Tick 中相同的计算方法
// 而不是简单的 lsit_XieLoulv.Average()
_Xieloulv = experData.CumulativeLeakageRate(
list_Tsi_Indoor_Data,
list_Tsi_Outdoor_Data,
experData.BenDiNongDu,
experData.YangPinXiShu);
}
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();
}));
}
}
private void InsertDataToDatabase()
{
float _Xieloulv = 0.0f;
_Xieloulv = experData.CumulativeLeakageRate(
list_Tsi_Indoor_Data,
list_Tsi_Outdoor_Data,
experData.BenDiNongDu,
experData.YangPinXiShu);
// 读取用户数据
_定制款..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.ToFloat();
experData.Mask_TSINongDu = Tsi.Outdoor_Data.ToFloat();
//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();
}
/// <summary>
/// 原先的方法
/// </summary>
//private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
//{
// switch (comboBox1.SelectedIndex)
// {
// case 0:
// lb_status.Text = "头部静止,不说话";
// //experData.TestStatus = "头部静止,不说话";
// // form2.uiLabel1.Text = "头部静止,不说话";
// _logger.Log(loginData.UserName, "切换了实验状态为【头部静止,不说话】", loginData.UserPower.ToString());
// break;
// case 1:
// lb_status.Text = "左右转动头部看检测仓左右墙壁大约15次";
// // experData.TestStatus = "左右转动头部看检测仓左右墙壁大约15次";
// //form2.uiLabel1.Text = "左右转动头部看检测仓左右墙壁大约15次";
// _logger.Log(loginData.UserName, "切换了实验状态为【左右转动头部看检测仓左右墙壁大约15次】", loginData.UserPower.ToString());
// break;
// case 2:
// lb_status.Text = "抬头和低头看检测仓和地面大约15次";
// // experData.TestStatus = "抬头和低头看检测仓和地面大约15次";
// // form2.uiLabel1.Text = "抬头和低头看检测仓和地面大约15次";
// _logger.Log(loginData.UserName, "切换了实验状态为【抬头和低头看检测仓和地面大约15次】", loginData.UserPower.ToString());
// break;
// case 3:
// lb_status.Text = "大声阅读一段文字或大声说话";
// // experData.TestStatus = "大声阅读一段文字或大声说话";
// // form2.uiLabel1.Text = "大声阅读一段文字或大声说话";
// _logger.Log(loginData.UserName, "切换了实验状态为【大声阅读一段文字或大声说话】", loginData.UserPower.ToString());
// break;
// case 4:
// lb_status.Text = "头部静止,不说话";
// // experData.TestStatus = "头部静止,不说话";
// // form2.uiLabel1.Text = "头部静止,不说话";
// _logger.Log(loginData.UserName, "切换了实验状态为【头部静止,不说话】", loginData.UserPower.ToString());
// break;
// }
//}
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>();//环境湿度
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);
experData.XieLouLv = experData.CumulativeLeakageRate(list_Tsi_Indoor_Data, list_Tsi_Outdoor_Data, experData.BenDiNongDu, experData.YangPinXiShu);
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
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.YangPinXiShu = config.ParticleSize;
experData.ExperName = config.Category;
}
isPaused = false;
Pause1.Text = "暂停测试";
Pause1.Style = UIStyle.Red;
//if (experData.BenDiNongDu == 0.0f)//add by xyy
////if (false)
//{
// MessageBox.Show("未校准本底浓度!");
// return;
//}
//else
//{
// 清空数据
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());
}
}
}