首次提交

This commit is contained in:
XingCheng3
2026-05-11 11:09:04 +08:00
commit 79c0f9cd43
260 changed files with 33504 additions and 0 deletions

184
SCADA/Pages/CrudHelper.cs Normal file
View File

@@ -0,0 +1,184 @@
using System;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Windows.Forms;
namespace MesWork.Pages
{
/// <summary>
/// CRUD页面通用辅助方法搜索框交互、弹窗控件创建、Excel导出
/// </summary>
public static class CrudHelper
{
// ====================================================================
// 搜索框占位提示交互
// ====================================================================
/// <summary>
/// 搜索框获得焦点时清除占位提示
/// </summary>
public static void SearchBox_GotFocus(TextBox txt, string hint)
{
if (txt.Text == hint) { txt.Text = ""; txt.ForeColor = Color.FromArgb(31, 41, 55); }
}
/// <summary>
/// 搜索框失去焦点时恢复占位提示
/// </summary>
public static void SearchBox_LostFocus(TextBox txt, string hint)
{
if (string.IsNullOrWhiteSpace(txt.Text)) { txt.Text = hint; txt.ForeColor = Color.FromArgb(156, 163, 175); }
}
/// <summary>
/// 搜索框回车触发搜索
/// </summary>
public static bool SearchBox_KeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter) { e.SuppressKeyPress = true; return true; }
return false;
}
/// <summary>
/// 获取搜索框的实际搜索关键词(排除占位提示)
/// </summary>
public static string GetSearchKeyword(TextBox txt, string hint)
{
return txt.Text == hint ? "" : txt.Text.Trim();
}
// ====================================================================
// 编辑弹窗辅助
// ====================================================================
/// <summary>
/// 创建标准编辑弹窗框架(统一样式 + 确定/取消按钮)
/// </summary>
public static Form CreateEditDialog(string title, int width, int height)
{
var dlg = new Form
{
Text = title,
Size = new Size(width, height),
StartPosition = FormStartPosition.CenterParent,
FormBorderStyle = FormBorderStyle.FixedDialog,
MaximizeBox = false,
MinimizeBox = false,
BackColor = Color.White,
Font = new Font("微软雅黑", 11F)
};
return dlg;
}
/// <summary>
/// 向弹窗添加确定/取消按钮
/// </summary>
public static (Button btnOk, Button btnCancel) AddDialogButtons(Form dlg, ref int y)
{
y += 16;
var btnOk = new Button
{
Text = "确 定", BackColor = Color.FromArgb(74, 144, 217), ForeColor = Color.White,
FlatStyle = FlatStyle.Flat, Size = new Size(120, 36), Location = new Point(80, y),
DialogResult = DialogResult.OK
};
btnOk.FlatAppearance.BorderSize = 0;
var btnCancel = new Button
{
Text = "取 消", BackColor = Color.FromArgb(229, 231, 235), ForeColor = Color.FromArgb(55, 65, 81),
FlatStyle = FlatStyle.Flat, Size = new Size(120, 36), Location = new Point(220, y),
DialogResult = DialogResult.Cancel
};
btnCancel.FlatAppearance.BorderSize = 0;
dlg.Controls.Add(btnOk);
dlg.Controls.Add(btnCancel);
dlg.AcceptButton = btnOk;
dlg.CancelButton = btnCancel;
return (btnOk, btnCancel);
}
/// <summary>
/// 向弹窗添加文本输入字段
/// </summary>
public static TextBox AddTextField(Form dlg, string label, ref int y, string value, int labelX = 30, int inputX = 130, int inputWidth = 240, bool isPassword = false)
{
dlg.Controls.Add(new Label { Text = label, Location = new Point(labelX, y + 4), AutoSize = true });
var txt = new TextBox { Text = value ?? "", Location = new Point(inputX, y), Size = new Size(inputWidth, 28), BorderStyle = BorderStyle.FixedSingle };
if (isPassword) txt.PasswordChar = '*';
dlg.Controls.Add(txt);
y += 42;
return txt;
}
/// <summary>
/// 向弹窗添加下拉选择字段
/// </summary>
public static ComboBox AddComboField(Form dlg, string label, ref int y, string[] items, string selected, int labelX = 30, int inputX = 130, int inputWidth = 240)
{
dlg.Controls.Add(new Label { Text = label, Location = new Point(labelX, y + 4), AutoSize = true });
var cmb = new ComboBox { Location = new Point(inputX, y), Size = new Size(inputWidth, 28), DropDownStyle = ComboBoxStyle.DropDownList };
cmb.Items.AddRange(items);
cmb.Text = selected ?? items[0];
dlg.Controls.Add(cmb);
y += 42;
return cmb;
}
// ====================================================================
// 导出Excel通用方法
// ====================================================================
/// <summary>
/// 通用的Excel导出流程弹出保存对话框→查全量数据→NPOI导出→打开文件位置
/// </summary>
/// <param name="sheetName">Excel工作表名称如"工件管理"</param>
/// <param name="defaultFileName">默认文件名(如"工件管理",会自动加时间后缀)</param>
/// <param name="queryAllData">查询全量数据的委托返回DataTable</param>
/// <param name="hasData">当前是否有数据可导出</param>
public static void ExportToExcel(string sheetName, string defaultFileName, Func<DataTable> queryAllData, bool hasData)
{
if (!hasData)
{
MessageBox.Show("没有数据可导出,请先查询", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
using (var sfd = new SaveFileDialog())
{
sfd.Filter = "Excel 文件|*.xlsx";
sfd.FileName = $"{defaultFileName}_{DateTime.Now:yyyyMMdd_HHmmss}.xlsx";
sfd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
if (sfd.ShowDialog() == DialogResult.OK)
{
try
{
DataTable dt = queryAllData();
if (dt != null && dt.Rows.Count > 0)
{
bool exported = NPOITest.ExeclHelper.DataTableToExcel(dt, sheetName, sfd.FileName);
if (exported)
{
MessageBox.Show($"导出成功!共 {dt.Rows.Count} 条记录", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{sfd.FileName}\"");
}
else
{
MessageBox.Show("导出失败,请检查文件是否被占用", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
MessageBox.Show("查询全量数据失败,请重试", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
catch (Exception ex)
{
MessageBox.Show($"导出失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
}
}

177
SCADA/Pages/PagerBar.cs Normal file
View File

@@ -0,0 +1,177 @@
using System;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Windows.Forms;
namespace MesWork.Pages
{
/// <summary>
/// 通用分页状态栏控件 — 嵌入到任何页面底部
/// 包含:记录数标签 | 每页条数下拉 | 上一页 | 页码信息 | 下一页
/// </summary>
public class PagerBar : Panel
{
public event EventHandler PageChanged;
private Label lbl_RecordCount;
private ComboBox cmb_PageSize;
private Button btn_Prev;
private Label lbl_PageInfo;
private Button btn_Next;
private int _currentPage = 1;
private int _totalPage = 1;
private int _totalCount = 0;
private int _pageSize = 100;
public int CurrentPage => _currentPage;
public int PageSize => _pageSize;
public int TotalCount => _totalCount;
public PagerBar()
{
this.BackColor = Color.White;
this.Dock = DockStyle.Bottom;
this.Height = 40;
var tbl = new TableLayoutPanel
{
Dock = DockStyle.Fill,
ColumnCount = 2,
RowCount = 1
};
tbl.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
tbl.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
tbl.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
this.Controls.Add(tbl);
// 左侧 — 记录数
lbl_RecordCount = new Label
{
AutoSize = true,
Anchor = AnchorStyles.Left,
Font = new Font("微软雅黑", 10F),
ForeColor = Color.FromArgb(55, 65, 81),
Margin = new Padding(16, 0, 0, 0),
Text = "共 0 条记录"
};
tbl.Controls.Add(lbl_RecordCount, 0, 0);
// 右侧 — 分页控件 (RightToLeft)
var flow = new FlowLayoutPanel
{
Dock = DockStyle.Fill,
FlowDirection = FlowDirection.RightToLeft,
WrapContents = false
};
tbl.Controls.Add(flow, 1, 0);
// 下一页
btn_Next = CreatePageButton("下一页 ▶");
btn_Next.Click += (s, e) => { if (_currentPage < _totalPage) { _currentPage++; PageChanged?.Invoke(this, EventArgs.Empty); } };
flow.Controls.Add(btn_Next);
// 页码信息
lbl_PageInfo = new Label
{
AutoSize = true,
Font = new Font("微软雅黑", 10F),
ForeColor = Color.FromArgb(55, 65, 81),
Margin = new Padding(4, 10, 4, 0),
Text = "第 1 页 / 共 1 页"
};
flow.Controls.Add(lbl_PageInfo);
// 上一页
btn_Prev = CreatePageButton("◀ 上一页");
btn_Prev.Click += (s, e) => { if (_currentPage > 1) { _currentPage--; PageChanged?.Invoke(this, EventArgs.Empty); } };
flow.Controls.Add(btn_Prev);
// 每页条数下拉
cmb_PageSize = new ComboBox
{
DropDownStyle = ComboBoxStyle.DropDownList,
Font = new Font("微软雅黑", 9F),
Size = new Size(70, 26),
Margin = new Padding(4, 7, 8, 0)
};
cmb_PageSize.Items.AddRange(new object[] { "50", "100", "200", "500", "1000" });
cmb_PageSize.SelectedItem = "100";
cmb_PageSize.SelectedIndexChanged += (s, e) =>
{
_pageSize = int.Parse(cmb_PageSize.Text);
_currentPage = 1;
PageChanged?.Invoke(this, EventArgs.Empty);
};
flow.Controls.Add(cmb_PageSize);
var lblSize = new Label
{
AutoSize = true,
Font = new Font("微软雅黑", 9F),
ForeColor = Color.FromArgb(100, 116, 139),
Margin = new Padding(4, 11, 0, 0),
Text = "每页"
};
flow.Controls.Add(lblSize);
}
/// <summary>
/// 重置到第1页查询按钮调用
/// </summary>
public void ResetPage() => _currentPage = 1;
/// <summary>
/// 更新分页状态SP调用后调用
/// </summary>
public void UpdateState(SqlParameter pageCountParam, SqlParameter itemCountParam)
{
_totalPage = pageCountParam.Value != DBNull.Value ? Convert.ToInt32(pageCountParam.Value) : 1;
_totalCount = itemCountParam.Value != DBNull.Value ? Convert.ToInt32(itemCountParam.Value) : 0;
if (_totalPage < 1) _totalPage = 1;
lbl_RecordCount.Text = $"共 {_totalCount} 条记录";
lbl_PageInfo.Text = $"第 {_currentPage} 页 / 共 {_totalPage} 页";
btn_Prev.Enabled = _currentPage > 1;
btn_Next.Enabled = _currentPage < _totalPage;
}
/// <summary>
/// 简易更新(直接传总条数,不分页的模块用)
/// </summary>
public void UpdateCount(int count)
{
lbl_RecordCount.Text = $"共 {count} 条记录";
}
/// <summary>
/// 创建分页 Output 参数对
/// </summary>
public static (SqlParameter pageCount, SqlParameter itemCount) CreateOutputParams()
{
return (
new SqlParameter("@PageCount", SqlDbType.Int) { Direction = ParameterDirection.Output },
new SqlParameter("@ItemCount", SqlDbType.Int) { Direction = ParameterDirection.Output }
);
}
private Button CreatePageButton(string text)
{
var btn = new Button
{
BackColor = Color.FromArgb(74, 144, 217),
Cursor = Cursors.Hand,
FlatStyle = FlatStyle.Flat,
Font = new Font("微软雅黑", 9F, FontStyle.Bold),
ForeColor = Color.White,
Margin = new Padding(4, 6, 4, 0),
Size = new Size(72, 28),
Text = text,
UseVisualStyleBackColor = false
};
btn.FlatAppearance.BorderSize = 0;
return btn;
}
}
}

262
SCADA/Pages/UC_LogRecord.Designer.cs generated Normal file
View File

@@ -0,0 +1,262 @@
namespace MesWork.Pages
{
partial class UC_LogRecord
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
components.Dispose();
base.Dispose(disposing);
}
#region
private void InitializeComponent()
{
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle10 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle11 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle12 = new System.Windows.Forms.DataGridViewCellStyle();
this.pnl_Toolbar = new System.Windows.Forms.Panel();
this.btn_Export = new System.Windows.Forms.Button();
this.btn_Refresh = new System.Windows.Forms.Button();
this.btn_Query = new System.Windows.Forms.Button();
this.txt_Keyword = new System.Windows.Forms.TextBox();
this.cmb_Type = new System.Windows.Forms.ComboBox();
this.dtp_End = new System.Windows.Forms.DateTimePicker();
this.lbl_To = new System.Windows.Forms.Label();
this.dtp_Start = new System.Windows.Forms.DateTimePicker();
this.dgv_Data = new System.Windows.Forms.DataGridView();
this.pnl_Footer = new System.Windows.Forms.Panel();
this.lbl_RecordCount = new System.Windows.Forms.Label();
this.pnl_Toolbar.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dgv_Data)).BeginInit();
this.pnl_Footer.SuspendLayout();
this.SuspendLayout();
//
// pnl_Toolbar
//
this.pnl_Toolbar.BackColor = System.Drawing.Color.White;
this.pnl_Toolbar.Controls.Add(this.btn_Export);
this.pnl_Toolbar.Controls.Add(this.btn_Refresh);
this.pnl_Toolbar.Controls.Add(this.btn_Query);
this.pnl_Toolbar.Controls.Add(this.txt_Keyword);
this.pnl_Toolbar.Controls.Add(this.cmb_Type);
this.pnl_Toolbar.Controls.Add(this.dtp_End);
this.pnl_Toolbar.Controls.Add(this.lbl_To);
this.pnl_Toolbar.Controls.Add(this.dtp_Start);
this.pnl_Toolbar.Dock = System.Windows.Forms.DockStyle.Top;
this.pnl_Toolbar.Location = new System.Drawing.Point(0, 0);
this.pnl_Toolbar.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.pnl_Toolbar.Name = "pnl_Toolbar";
this.pnl_Toolbar.Padding = new System.Windows.Forms.Padding(18, 12, 18, 12);
this.pnl_Toolbar.Size = new System.Drawing.Size(2730, 75);
this.pnl_Toolbar.TabIndex = 2;
//
// btn_Export
//
this.btn_Export.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(5)))), ((int)(((byte)(150)))), ((int)(((byte)(105)))));
this.btn_Export.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Export.FlatAppearance.BorderSize = 0;
this.btn_Export.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Export.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Export.ForeColor = System.Drawing.Color.White;
this.btn_Export.Location = new System.Drawing.Point(1305, 12);
this.btn_Export.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.btn_Export.Name = "btn_Export";
this.btn_Export.Size = new System.Drawing.Size(180, 48);
this.btn_Export.TabIndex = 0;
this.btn_Export.Text = "📥 导出Excel";
this.btn_Export.UseVisualStyleBackColor = false;
this.btn_Export.Click += new System.EventHandler(this.btn_Export_Click);
//
// btn_Refresh
//
this.btn_Refresh.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(229)))), ((int)(((byte)(231)))), ((int)(((byte)(235)))));
this.btn_Refresh.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Refresh.FlatAppearance.BorderSize = 0;
this.btn_Refresh.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Refresh.Font = new System.Drawing.Font("微软雅黑", 10F);
this.btn_Refresh.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(65)))), ((int)(((byte)(81)))));
this.btn_Refresh.Location = new System.Drawing.Point(1170, 12);
this.btn_Refresh.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.btn_Refresh.Name = "btn_Refresh";
this.btn_Refresh.Size = new System.Drawing.Size(120, 48);
this.btn_Refresh.TabIndex = 1;
this.btn_Refresh.Text = "↻ 刷新";
this.btn_Refresh.UseVisualStyleBackColor = false;
this.btn_Refresh.Click += new System.EventHandler(this.btn_Refresh_Click);
//
// btn_Query
//
this.btn_Query.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(74)))), ((int)(((byte)(144)))), ((int)(((byte)(217)))));
this.btn_Query.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Query.FlatAppearance.BorderSize = 0;
this.btn_Query.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Query.Font = new System.Drawing.Font("微软雅黑", 10F);
this.btn_Query.ForeColor = System.Drawing.Color.White;
this.btn_Query.Location = new System.Drawing.Point(1035, 12);
this.btn_Query.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.btn_Query.Name = "btn_Query";
this.btn_Query.Size = new System.Drawing.Size(120, 48);
this.btn_Query.TabIndex = 2;
this.btn_Query.Text = "🔍 查询";
this.btn_Query.UseVisualStyleBackColor = false;
this.btn_Query.Click += new System.EventHandler(this.btn_Query_Click);
//
// txt_Keyword
//
this.txt_Keyword.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txt_Keyword.Font = new System.Drawing.Font("微软雅黑", 10F);
this.txt_Keyword.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(156)))), ((int)(((byte)(163)))), ((int)(((byte)(175)))));
this.txt_Keyword.Location = new System.Drawing.Point(712, 15);
this.txt_Keyword.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.txt_Keyword.Name = "txt_Keyword";
this.txt_Keyword.Size = new System.Drawing.Size(299, 34);
this.txt_Keyword.TabIndex = 3;
this.txt_Keyword.Text = "关键字搜索...";
//
// cmb_Type
//
this.cmb_Type.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cmb_Type.Font = new System.Drawing.Font("微软雅黑", 10F);
this.cmb_Type.Location = new System.Drawing.Point(480, 15);
this.cmb_Type.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.cmb_Type.Name = "cmb_Type";
this.cmb_Type.Size = new System.Drawing.Size(208, 35);
this.cmb_Type.TabIndex = 4;
//
// dtp_End
//
this.dtp_End.Font = new System.Drawing.Font("微软雅黑", 10F);
this.dtp_End.Format = System.Windows.Forms.DateTimePickerFormat.Short;
this.dtp_End.Location = new System.Drawing.Point(262, 15);
this.dtp_End.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.dtp_End.Name = "dtp_End";
this.dtp_End.Size = new System.Drawing.Size(193, 34);
this.dtp_End.TabIndex = 5;
//
// lbl_To
//
this.lbl_To.AutoSize = true;
this.lbl_To.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lbl_To.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(107)))), ((int)(((byte)(114)))), ((int)(((byte)(128)))));
this.lbl_To.Location = new System.Drawing.Point(222, 21);
this.lbl_To.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbl_To.Name = "lbl_To";
this.lbl_To.Size = new System.Drawing.Size(32, 27);
this.lbl_To.TabIndex = 6;
this.lbl_To.Text = "→";
//
// dtp_Start
//
this.dtp_Start.Font = new System.Drawing.Font("微软雅黑", 10F);
this.dtp_Start.Format = System.Windows.Forms.DateTimePickerFormat.Short;
this.dtp_Start.Location = new System.Drawing.Point(18, 15);
this.dtp_Start.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.dtp_Start.Name = "dtp_Start";
this.dtp_Start.Size = new System.Drawing.Size(193, 34);
this.dtp_Start.TabIndex = 7;
//
// dgv_Data
//
this.dgv_Data.AllowUserToAddRows = false;
this.dgv_Data.AllowUserToDeleteRows = false;
dataGridViewCellStyle10.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(250)))), ((int)(((byte)(252)))));
this.dgv_Data.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle10;
this.dgv_Data.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
this.dgv_Data.BackgroundColor = System.Drawing.Color.White;
this.dgv_Data.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.dgv_Data.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.SingleHorizontal;
dataGridViewCellStyle11.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
dataGridViewCellStyle11.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(232)))), ((int)(((byte)(237)))), ((int)(((byte)(242)))));
dataGridViewCellStyle11.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
dataGridViewCellStyle11.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(55)))), ((int)(((byte)(65)))), ((int)(((byte)(81)))));
dataGridViewCellStyle11.SelectionBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(232)))), ((int)(((byte)(237)))), ((int)(((byte)(242)))));
dataGridViewCellStyle11.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle11.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.dgv_Data.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle11;
this.dgv_Data.ColumnHeadersHeight = 36;
dataGridViewCellStyle12.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle12.BackColor = System.Drawing.SystemColors.Window;
dataGridViewCellStyle12.Font = new System.Drawing.Font("微软雅黑", 10F);
dataGridViewCellStyle12.ForeColor = System.Drawing.SystemColors.ControlText;
dataGridViewCellStyle12.SelectionBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(219)))), ((int)(((byte)(234)))), ((int)(((byte)(254)))));
dataGridViewCellStyle12.SelectionForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(58)))), ((int)(((byte)(95)))));
dataGridViewCellStyle12.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this.dgv_Data.DefaultCellStyle = dataGridViewCellStyle12;
this.dgv_Data.Dock = System.Windows.Forms.DockStyle.Fill;
this.dgv_Data.EnableHeadersVisualStyles = false;
this.dgv_Data.Font = new System.Drawing.Font("微软雅黑", 10F);
this.dgv_Data.GridColor = System.Drawing.Color.FromArgb(((int)(((byte)(232)))), ((int)(((byte)(237)))), ((int)(((byte)(242)))));
this.dgv_Data.Location = new System.Drawing.Point(0, 75);
this.dgv_Data.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.dgv_Data.Name = "dgv_Data";
this.dgv_Data.ReadOnly = true;
this.dgv_Data.RowHeadersVisible = false;
this.dgv_Data.RowHeadersWidth = 62;
this.dgv_Data.RowTemplate.Height = 32;
this.dgv_Data.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.dgv_Data.Size = new System.Drawing.Size(2730, 1371);
this.dgv_Data.TabIndex = 0;
//
// pnl_Footer
//
this.pnl_Footer.BackColor = System.Drawing.Color.White;
this.pnl_Footer.Controls.Add(this.lbl_RecordCount);
this.pnl_Footer.Dock = System.Windows.Forms.DockStyle.Bottom;
this.pnl_Footer.Location = new System.Drawing.Point(0, 1446);
this.pnl_Footer.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.pnl_Footer.Name = "pnl_Footer";
this.pnl_Footer.Size = new System.Drawing.Size(2730, 54);
this.pnl_Footer.TabIndex = 1;
//
// lbl_RecordCount
//
this.lbl_RecordCount.AutoSize = true;
this.lbl_RecordCount.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lbl_RecordCount.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(107)))), ((int)(((byte)(114)))), ((int)(((byte)(128)))));
this.lbl_RecordCount.Location = new System.Drawing.Point(18, 9);
this.lbl_RecordCount.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbl_RecordCount.Name = "lbl_RecordCount";
this.lbl_RecordCount.Size = new System.Drawing.Size(116, 27);
this.lbl_RecordCount.TabIndex = 0;
this.lbl_RecordCount.Text = "共 0 条记录";
//
// UC_LogRecord
//
this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(245)))), ((int)(((byte)(247)))), ((int)(((byte)(250)))));
this.Controls.Add(this.dgv_Data);
this.Controls.Add(this.pnl_Footer);
this.Controls.Add(this.pnl_Toolbar);
this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.Name = "UC_LogRecord";
this.Size = new System.Drawing.Size(2730, 1500);
this.pnl_Toolbar.ResumeLayout(false);
this.pnl_Toolbar.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dgv_Data)).EndInit();
this.pnl_Footer.ResumeLayout(false);
this.pnl_Footer.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel pnl_Toolbar;
private System.Windows.Forms.DateTimePicker dtp_Start;
private System.Windows.Forms.Label lbl_To;
private System.Windows.Forms.DateTimePicker dtp_End;
private System.Windows.Forms.ComboBox cmb_Type;
private System.Windows.Forms.TextBox txt_Keyword;
private System.Windows.Forms.Button btn_Query;
private System.Windows.Forms.Button btn_Refresh;
private System.Windows.Forms.Button btn_Export;
private System.Windows.Forms.DataGridView dgv_Data;
private System.Windows.Forms.Panel pnl_Footer;
private System.Windows.Forms.Label lbl_RecordCount;
}
}

209
SCADA/Pages/UC_LogRecord.cs Normal file
View File

@@ -0,0 +1,209 @@
using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
namespace MesWork.Pages
{
/// <summary>
/// 日志查询页面 — 现代化风格,统一 CRUD 模块设计
/// 直接查询 [记录_日志_项目运行日志] 表
/// </summary>
public partial class UC_LogRecord : UserControl
{
private const string KEYWORD_HINT = "关键字搜索...";
public UC_LogRecord()
{
InitializeComponent();
InitColumns();
InitFilterData();
// 绑定数据完成后自动着色
dgv_Data.DataBindingComplete += dgv_Data_DataBindingComplete;
}
private void InitColumns()
{
dgv_Data.AutoGenerateColumns = false;
dgv_Data.Columns.Clear();
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "AID", HeaderText = "AID", DataPropertyName = "AID", Visible = false });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "工位号", HeaderText = "工位号", DataPropertyName = "工位号", FillWeight = 70 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "类型", HeaderText = "类型", DataPropertyName = "类型", FillWeight = 70 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "请求时间", HeaderText = "请求时间", DataPropertyName = "请求时间", FillWeight = 100 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "请求内容", HeaderText = "请求内容", DataPropertyName = "请求内容", FillWeight = 200 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "响应时间", HeaderText = "响应时间", DataPropertyName = "响应时间", FillWeight = 100 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "响应内容", HeaderText = "响应内容", DataPropertyName = "响应内容", FillWeight = 200 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "CMD", HeaderText = "CMD", DataPropertyName = "CMD", FillWeight = 60 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "FROM", HeaderText = "FROM", DataPropertyName = "FROM", FillWeight = 50 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "TO", HeaderText = "TO", DataPropertyName = "TO", FillWeight = 50 });
}
private void InitFilterData()
{
// 日志类型下拉
cmb_Type.Items.Add("全部");
foreach (var name in Enum.GetNames(typeof(Log_Type)))
cmb_Type.Items.Add(name);
cmb_Type.SelectedIndex = 0;
// 日期范围
dtp_End.Value = DateTime.Now.AddDays(1);
dtp_Start.Value = DateTime.Now.AddDays(-3);
// 搜索框事件
txt_Keyword.GotFocus += (s, e) => { if (txt_Keyword.Text == KEYWORD_HINT) { txt_Keyword.Text = ""; txt_Keyword.ForeColor = Color.FromArgb(31, 41, 55); } };
txt_Keyword.LostFocus += (s, e) => { if (string.IsNullOrWhiteSpace(txt_Keyword.Text)) { txt_Keyword.Text = KEYWORD_HINT; txt_Keyword.ForeColor = Color.FromArgb(156, 163, 175); } };
txt_Keyword.KeyDown += (s, e) => { if (e.KeyCode == Keys.Enter) { btn_Query_Click(s, e); e.SuppressKeyPress = true; } };
}
// ====================================================================
// 查询
// ====================================================================
private void btn_Query_Click(object sender, EventArgs e)
{
try
{
string sql = BuildQuerySql();
DataLinkMesWork.SQLCommon.ExecuteDataTable(sql, MesWorkForm.ConnectionString, out DataTable dt, out string err);
if (dt != null)
{
dgv_Data.DataSource = dt;
lbl_RecordCount.Text = $"共 {dt.Rows.Count} 条记录";
}
}
catch (Exception ex)
{
MessageBox.Show($"查询失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 数据绑定完成后按日志类型着色(首次加载和每次查询都会触发)
/// </summary>
private void dgv_Data_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
for (int i = 0; i < dgv_Data.Rows.Count; i++)
{
string typeStr = dgv_Data.Rows[i].Cells["类型"]?.Value?.ToString() ?? "";
Color rowColor;
switch (typeStr)
{
case "ZK_Alarm":
case "ZK_Delete":
rowColor = Color.FromArgb(254, 226, 226); // 红底
break;
case "ZK_Login":
rowColor = Color.FromArgb(220, 252, 231); // 绿底
break;
case "ZK_Tip":
rowColor = Color.FromArgb(254, 249, 195); // 黄底
break;
default:
rowColor = (i % 2 == 0) ? Color.White : Color.FromArgb(248, 250, 252);
break;
}
dgv_Data.Rows[i].DefaultCellStyle.BackColor = rowColor;
}
dgv_Data.ClearSelection();
}
/// <summary>
/// 导出 Excel重新查询全量数据后导出
/// </summary>
private void btn_Export_Click(object sender, EventArgs e)
{
if (dgv_Data.Rows.Count == 0)
{
MessageBox.Show("没有数据可导出,请先查询", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
using (var sfd = new SaveFileDialog())
{
sfd.Filter = "Excel 文件|*.xlsx";
sfd.FileName = $"运行日志_{DateTime.Now:yyyyMMdd_HHmmss}.xlsx";
sfd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
if (sfd.ShowDialog() == DialogResult.OK)
{
try
{
string sql = BuildQuerySql();
DataLinkMesWork.SQLCommon.ExecuteDataTable(sql, MesWorkForm.ConnectionString, out DataTable dt, out string err);
if (dt != null && dt.Rows.Count > 0)
{
bool exported = NPOITest.ExeclHelper.DataTableToExcel(dt, "运行日志", sfd.FileName);
if (exported)
{
MessageBox.Show($"导出成功!共 {dt.Rows.Count} 条记录", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{sfd.FileName}\"");
}
else
{
MessageBox.Show("导出失败,请检查文件是否被占用", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
MessageBox.Show("查询数据失败,请重试", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
catch (Exception ex)
{
MessageBox.Show($"导出失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
/// <summary>
/// 根据当前筛选条件构建日志查询SQL查询和导出共用
/// </summary>
private string BuildQuerySql(bool includeAID = true)
{
var start = dtp_Start.Value;
var end = dtp_End.Value;
string keyword = txt_Keyword.Text == KEYWORD_HINT ? "" : txt_Keyword.Text.Trim();
string logType = cmb_Type.Text == "全部" ? "" : cmb_Type.Text;
string where = $" AND [请求时间] >= '{start:G}' AND [请求时间] < '{end:yyyy-MM-dd 23:59:59}'";
if (!string.IsNullOrEmpty(keyword))
where += $" AND ([请求内容] LIKE '%{keyword}%' OR [响应内容] LIKE '%{keyword}%' OR [工位号] LIKE '%{keyword}%')";
if (!string.IsNullOrEmpty(logType))
where += $" AND [日志类型] = '{logType}'";
string sql =
" SELECT [工位号] '工位号'" +
",[日志类型] '类型'" +
",[请求时间] '请求时间'" +
",[请求内容] '请求内容'" +
",[响应时间] '响应时间'" +
",[响应内容] '响应内容'" +
",[请求CMD] 'CMD'" +
",[请求FROM] 'FROM'" +
",[请求TO] 'TO'" +
(includeAID ? ",[AID] 'AID'" : "") +
" FROM [记录_日志_项目运行日志]" +
" WHERE 1=1 " + where +
" ORDER BY [请求时间] DESC";
return sql;
}
private void btn_Refresh_Click(object sender, EventArgs e)
{
cmb_Type.SelectedIndex = 0;
txt_Keyword.Text = KEYWORD_HINT;
txt_Keyword.ForeColor = Color.FromArgb(156, 163, 175);
dtp_Start.Value = DateTime.Now.AddDays(-3);
dtp_End.Value = DateTime.Now.AddDays(1);
btn_Query_Click(sender, e);
}
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
if (Visible && dgv_Data.DataSource == null)
btn_Query_Click(this, EventArgs.Empty);
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

207
SCADA/Pages/UC_Report.Designer.cs generated Normal file
View File

@@ -0,0 +1,207 @@
namespace MesWork.Pages
{
partial class UC_Report
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
components.Dispose();
base.Dispose(disposing);
}
#region
private void InitializeComponent()
{
this.pnl_QueryBar = new System.Windows.Forms.Panel();
this.lbl_DateFrom = new System.Windows.Forms.Label();
this.dtp_Start = new System.Windows.Forms.DateTimePicker();
this.lbl_DateTo = new System.Windows.Forms.Label();
this.dtp_End = new System.Windows.Forms.DateTimePicker();
this.lbl_EngineNo = new System.Windows.Forms.Label();
this.txt_EngineNo = new System.Windows.Forms.TextBox();
this.lbl_ModelNo = new System.Windows.Forms.Label();
this.txt_ModelNo = new System.Windows.Forms.TextBox();
this.btn_Query = new System.Windows.Forms.Button();
this.btn_Export = new System.Windows.Forms.Button();
this.dgv_Data = new System.Windows.Forms.DataGridView();
this.pnl_StatusBar = new System.Windows.Forms.Panel();
this.pnl_QueryBar.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dgv_Data)).BeginInit();
this.SuspendLayout();
//
// pnl_QueryBar — 查询条件栏
//
this.pnl_QueryBar.BackColor = System.Drawing.Color.White;
this.pnl_QueryBar.Controls.Add(this.btn_Export);
this.pnl_QueryBar.Controls.Add(this.btn_Query);
this.pnl_QueryBar.Controls.Add(this.txt_ModelNo);
this.pnl_QueryBar.Controls.Add(this.lbl_ModelNo);
this.pnl_QueryBar.Controls.Add(this.txt_EngineNo);
this.pnl_QueryBar.Controls.Add(this.lbl_EngineNo);
this.pnl_QueryBar.Controls.Add(this.dtp_End);
this.pnl_QueryBar.Controls.Add(this.lbl_DateTo);
this.pnl_QueryBar.Controls.Add(this.dtp_Start);
this.pnl_QueryBar.Controls.Add(this.lbl_DateFrom);
this.pnl_QueryBar.Dock = System.Windows.Forms.DockStyle.Top;
this.pnl_QueryBar.Height = 56;
this.pnl_QueryBar.Name = "pnl_QueryBar";
this.pnl_QueryBar.Padding = new System.Windows.Forms.Padding(16, 12, 16, 12);
//
// 日期范围
//
this.lbl_DateFrom.AutoSize = true;
this.lbl_DateFrom.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lbl_DateFrom.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_DateFrom.Location = new System.Drawing.Point(16, 17);
this.lbl_DateFrom.Name = "lbl_DateFrom";
this.lbl_DateFrom.Text = "从";
//
this.dtp_Start.Font = new System.Drawing.Font("微软雅黑", 10F);
this.dtp_Start.Format = System.Windows.Forms.DateTimePickerFormat.Short;
this.dtp_Start.Location = new System.Drawing.Point(40, 13);
this.dtp_Start.Name = "dtp_Start";
this.dtp_Start.Size = new System.Drawing.Size(130, 25);
//
this.lbl_DateTo.AutoSize = true;
this.lbl_DateTo.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lbl_DateTo.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_DateTo.Location = new System.Drawing.Point(178, 17);
this.lbl_DateTo.Name = "lbl_DateTo";
this.lbl_DateTo.Text = "到";
//
this.dtp_End.Font = new System.Drawing.Font("微软雅黑", 10F);
this.dtp_End.Format = System.Windows.Forms.DateTimePickerFormat.Short;
this.dtp_End.Location = new System.Drawing.Point(200, 13);
this.dtp_End.Name = "dtp_End";
this.dtp_End.Size = new System.Drawing.Size(130, 25);
//
// 发动机号
//
this.lbl_EngineNo.AutoSize = true;
this.lbl_EngineNo.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lbl_EngineNo.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_EngineNo.Location = new System.Drawing.Point(360, 17);
this.lbl_EngineNo.Name = "lbl_EngineNo";
this.lbl_EngineNo.Text = "发动机号";
this.txt_EngineNo.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txt_EngineNo.Font = new System.Drawing.Font("微软雅黑", 10F);
this.txt_EngineNo.Location = new System.Drawing.Point(430, 13);
this.txt_EngineNo.Name = "txt_EngineNo";
this.txt_EngineNo.Size = new System.Drawing.Size(160, 25);
//
// 机型号
//
this.lbl_ModelNo.AutoSize = true;
this.lbl_ModelNo.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lbl_ModelNo.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_ModelNo.Location = new System.Drawing.Point(610, 17);
this.lbl_ModelNo.Name = "lbl_ModelNo";
this.lbl_ModelNo.Text = "机型号";
this.txt_ModelNo.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txt_ModelNo.Font = new System.Drawing.Font("微软雅黑", 10F);
this.txt_ModelNo.Location = new System.Drawing.Point(666, 13);
this.txt_ModelNo.Name = "txt_ModelNo";
this.txt_ModelNo.Size = new System.Drawing.Size(160, 25);
//
// btn_Query — 查询
//
this.btn_Query.BackColor = System.Drawing.Color.FromArgb(74, 144, 217);
this.btn_Query.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Query.FlatAppearance.BorderSize = 0;
this.btn_Query.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Query.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Query.ForeColor = System.Drawing.Color.White;
this.btn_Query.Location = new System.Drawing.Point(850, 12);
this.btn_Query.Name = "btn_Query";
this.btn_Query.Size = new System.Drawing.Size(88, 30);
this.btn_Query.Text = "🔍 查询";
this.btn_Query.UseVisualStyleBackColor = false;
this.btn_Query.Click += new System.EventHandler(this.btn_Query_Click);
//
// btn_Export — 导出Excel
//
this.btn_Export.BackColor = System.Drawing.Color.FromArgb(5, 150, 105);
this.btn_Export.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Export.FlatAppearance.BorderSize = 0;
this.btn_Export.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Export.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Export.ForeColor = System.Drawing.Color.White;
this.btn_Export.Location = new System.Drawing.Point(950, 12);
this.btn_Export.Name = "btn_Export";
this.btn_Export.Size = new System.Drawing.Size(104, 30);
this.btn_Export.Text = "📥 导出 Excel";
this.btn_Export.UseVisualStyleBackColor = false;
this.btn_Export.Click += new System.EventHandler(this.btn_Export_Click);
//
// dgv_Data — 数据表格
//
this.dgv_Data.AllowUserToAddRows = false;
this.dgv_Data.AllowUserToDeleteRows = false;
this.dgv_Data.AllowUserToResizeRows = false;
this.dgv_Data.BackgroundColor = System.Drawing.Color.White;
this.dgv_Data.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.dgv_Data.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.SingleHorizontal;
this.dgv_Data.ColumnHeadersHeight = 42;
this.dgv_Data.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
this.dgv_Data.ColumnHeadersDefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(232, 237, 242);
this.dgv_Data.ColumnHeadersDefaultCellStyle.ForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
this.dgv_Data.ColumnHeadersDefaultCellStyle.Font = new System.Drawing.Font("微软雅黑", 11F, System.Drawing.FontStyle.Bold);
this.dgv_Data.DefaultCellStyle.ForeColor = System.Drawing.Color.FromArgb(31, 41, 55);
this.dgv_Data.DefaultCellStyle.Font = new System.Drawing.Font("微软雅黑", 11F);
this.dgv_Data.DefaultCellStyle.SelectionBackColor = System.Drawing.Color.FromArgb(219, 234, 254);
this.dgv_Data.DefaultCellStyle.SelectionForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
this.dgv_Data.AlternatingRowsDefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(248, 250, 252);
this.dgv_Data.Dock = System.Windows.Forms.DockStyle.Fill;
this.dgv_Data.EnableHeadersVisualStyles = false;
this.dgv_Data.GridColor = System.Drawing.Color.FromArgb(229, 231, 235);
this.dgv_Data.MultiSelect = false;
this.dgv_Data.Name = "dgv_Data";
this.dgv_Data.ReadOnly = true;
this.dgv_Data.RowHeadersVisible = false;
this.dgv_Data.RowTemplate.Height = 38;
this.dgv_Data.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.dgv_Data.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
//
// pnl_StatusBar — 占位构造函数中会被PagerBar替换
//
this.pnl_StatusBar.BackColor = System.Drawing.Color.White;
this.pnl_StatusBar.Dock = System.Windows.Forms.DockStyle.Bottom;
this.pnl_StatusBar.Height = 40;
this.pnl_StatusBar.Name = "pnl_StatusBar";
//
// UC_Report
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.Color.FromArgb(245, 247, 250);
this.Controls.Add(this.dgv_Data);
this.Controls.Add(this.pnl_StatusBar);
this.Controls.Add(this.pnl_QueryBar);
this.Name = "UC_Report";
this.Size = new System.Drawing.Size(1820, 1000);
this.pnl_QueryBar.ResumeLayout(false);
this.pnl_QueryBar.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dgv_Data)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel pnl_QueryBar;
private System.Windows.Forms.Label lbl_DateFrom;
private System.Windows.Forms.DateTimePicker dtp_Start;
private System.Windows.Forms.Label lbl_DateTo;
private System.Windows.Forms.DateTimePicker dtp_End;
private System.Windows.Forms.Label lbl_EngineNo;
private System.Windows.Forms.TextBox txt_EngineNo;
private System.Windows.Forms.Label lbl_ModelNo;
private System.Windows.Forms.TextBox txt_ModelNo;
private System.Windows.Forms.Button btn_Query;
private System.Windows.Forms.Button btn_Export;
private System.Windows.Forms.DataGridView dgv_Data;
private System.Windows.Forms.Panel pnl_StatusBar;
}
}

153
SCADA/Pages/UC_Report.cs Normal file
View File

@@ -0,0 +1,153 @@
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
namespace MesWork.Pages
{
/// <summary>
/// 报告查询页面 — 历史称重数据检索与 Excel 导出
/// 对应存储过程称重记录_分页查询使用 sp_xt_pagesplit 真分页)
/// </summary>
public partial class UC_Report : UserControl
{
private PagerBar _pager;
public UC_Report()
{
InitializeComponent();
InitColumns();
dtp_Start.Value = DateTime.Today.AddDays(-7);
dtp_End.Value = DateTime.Today;
// 用PagerBar替换原始pnl_StatusBar
_pager = new PagerBar();
_pager.PageChanged += (s, e) => LoadData();
this.Controls.Remove(pnl_StatusBar);
this.Controls.Add(_pager);
this.Controls.SetChildIndex(_pager, this.Controls.Count - 2);
}
/// <summary>
/// 预设表格列
/// </summary>
private void InitColumns()
{
dgv_Data.AutoGenerateColumns = false;
dgv_Data.Columns.Clear();
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "ID", HeaderText = "ID", DataPropertyName = "ID", Visible = false });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "发动机号", HeaderText = "发动机号", DataPropertyName = "发动机号", FillWeight = 100 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "机型号", HeaderText = "机型号", DataPropertyName = "机型号", FillWeight = 80 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "订单号", HeaderText = "订单号", DataPropertyName = "订单号", FillWeight = 80 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "称重类型", HeaderText = "称重类型", DataPropertyName = "称重类型", FillWeight = 70 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "托盘号", HeaderText = "托盘号", DataPropertyName = "托盘号", FillWeight = 60 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "进站重量", HeaderText = "进站重量(KG)", DataPropertyName = "进站重量", FillWeight = 80 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "离站重量", HeaderText = "离站重量(KG)", DataPropertyName = "离站重量", FillWeight = 80 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "加油量", HeaderText = "加油量", DataPropertyName = "加油量", FillWeight = 60 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "抽油量", HeaderText = "抽油量", DataPropertyName = "抽油量", FillWeight = 60 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "放油量", HeaderText = "放油量", DataPropertyName = "放油量", FillWeight = 70 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "残留量", HeaderText = "残留量", DataPropertyName = "残留量", FillWeight = 60 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "油密度", HeaderText = "油密度", DataPropertyName = "油密度", FillWeight = 60 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "合格标志", HeaderText = "合格", DataPropertyName = "合格标志", FillWeight = 50 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "操作员", HeaderText = "操作员", DataPropertyName = "操作员", FillWeight = 60 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "进站时间", HeaderText = "检测时间", DataPropertyName = "进站时间", FillWeight = 100 });
}
/// <summary>
/// 查询按钮重置到第1页后查询
/// </summary>
private void btn_Query_Click(object sender, EventArgs e)
{
_pager.ResetPage();
LoadData();
}
/// <summary>
/// 核心查询方法
/// </summary>
private void LoadData()
{
try
{
var (pageCountParam, itemCountParam) = PagerBar.CreateOutputParams();
var parms = new SqlParameter[]
{
new SqlParameter("@发动机号", txt_EngineNo.Text.Trim()),
new SqlParameter("@机型号", txt_ModelNo.Text.Trim()),
new SqlParameter("@开始时间", dtp_Start.Value.ToString("yyyy-MM-dd")),
new SqlParameter("@结束时间", dtp_End.Value.AddDays(1).ToString("yyyy-MM-dd")),
new SqlParameter("@PageCurrent", _pager.CurrentPage),
new SqlParameter("@PageSize", _pager.PageSize),
pageCountParam,
itemCountParam
};
SqlOperation.ExecuteStoredProcedure("称重记录_分页查询", parms, out DataTable dt, out string err);
if (dt != null) dgv_Data.DataSource = dt;
_pager.UpdateState(pageCountParam, itemCountParam);
}
catch (Exception ex)
{
MessageBox.Show($"查询失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 导出 Excel重新查询全量数据后导出
/// </summary>
private void btn_Export_Click(object sender, EventArgs e)
{
if (dgv_Data.Rows.Count == 0)
{
MessageBox.Show("没有数据可导出,请先查询", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
using (var sfd = new SaveFileDialog())
{
sfd.Filter = "Excel 文件|*.xlsx";
sfd.FileName = $"称重报告_{DateTime.Now:yyyyMMdd_HHmmss}.xlsx";
sfd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
if (sfd.ShowDialog() == DialogResult.OK)
{
try
{
// 用当前查询条件重新查询全量数据(不受分页限制)
var (pageCountParam, itemCountParam) = PagerBar.CreateOutputParams();
var parms = new SqlParameter[]
{
new SqlParameter("@发动机号", txt_EngineNo.Text.Trim()),
new SqlParameter("@机型号", txt_ModelNo.Text.Trim()),
new SqlParameter("@开始时间", dtp_Start.Value.ToString("yyyy-MM-dd")),
new SqlParameter("@结束时间", dtp_End.Value.AddDays(1).ToString("yyyy-MM-dd")),
new SqlParameter("@PageCurrent", 1),
new SqlParameter("@PageSize", 9999999),
pageCountParam,
itemCountParam
};
SqlOperation.ExecuteStoredProcedure("称重记录_分页查询", parms, out DataTable dt, out string err);
if (dt != null && dt.Rows.Count > 0)
{
bool exported = NPOITest.ExeclHelper.DataTableToExcel(dt, "称重记录", sfd.FileName);
if (exported)
{
MessageBox.Show($"导出成功!共 {dt.Rows.Count} 条记录", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{sfd.FileName}\"");
}
else
{
MessageBox.Show("导出失败,请检查文件是否被占用", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
MessageBox.Show("查询全量数据失败,请重试", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
catch (Exception ex)
{
MessageBox.Show($"导出失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
}
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata"><xsd:complexType><xsd:sequence><xsd:element name="value" type="xsd:string" minOccurs="0" /></xsd:sequence><xsd:attribute name="name" use="required" type="xsd:string" /><xsd:attribute name="type" type="xsd:string" /><xsd:attribute name="mimetype" type="xsd:string" /><xsd:attribute ref="xml:space" /></xsd:complexType></xsd:element>
<xsd:element name="assembly"><xsd:complexType><xsd:attribute name="alias" type="xsd:string" /><xsd:attribute name="name" type="xsd:string" /></xsd:complexType></xsd:element>
<xsd:element name="data"><xsd:complexType><xsd:sequence><xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /><xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /></xsd:sequence><xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /><xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /><xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /><xsd:attribute ref="xml:space" /></xsd:complexType></xsd:element>
<xsd:element name="resheader"><xsd:complexType><xsd:sequence><xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /></xsd:sequence><xsd:attribute name="name" type="xsd:string" use="required" /></xsd:complexType></xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype"><value>text/microsoft-resx</value></resheader>
<resheader name="version"><value>2.0</value></resheader>
<resheader name="reader"><value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader>
<resheader name="writer"><value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader>
</root>

186
SCADA/Pages/UC_StationRecord.Designer.cs generated Normal file
View File

@@ -0,0 +1,186 @@
namespace MesWork.Pages
{
partial class UC_StationRecord
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
components.Dispose();
base.Dispose(disposing);
}
#region
private void InitializeComponent()
{
this.pnl_QueryBar = new System.Windows.Forms.Panel();
this.lbl_DateFrom = new System.Windows.Forms.Label();
this.dtp_Start = new System.Windows.Forms.DateTimePicker();
this.lbl_DateTo = new System.Windows.Forms.Label();
this.dtp_End = new System.Windows.Forms.DateTimePicker();
this.lbl_EngineNo = new System.Windows.Forms.Label();
this.txt_EngineNo = new System.Windows.Forms.TextBox();
this.lbl_ModelNo = new System.Windows.Forms.Label();
this.txt_ModelNo = new System.Windows.Forms.TextBox();
this.btn_Query = new System.Windows.Forms.Button();
this.btn_Export = new System.Windows.Forms.Button();
this.dgv_Data = new System.Windows.Forms.DataGridView();
this.pnl_StatusBar = new System.Windows.Forms.Panel();
this.pnl_QueryBar.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dgv_Data)).BeginInit();
this.SuspendLayout();
// pnl_QueryBar
this.pnl_QueryBar.BackColor = System.Drawing.Color.White;
this.pnl_QueryBar.Controls.Add(this.btn_Export);
this.pnl_QueryBar.Controls.Add(this.btn_Query);
this.pnl_QueryBar.Controls.Add(this.txt_ModelNo);
this.pnl_QueryBar.Controls.Add(this.lbl_ModelNo);
this.pnl_QueryBar.Controls.Add(this.txt_EngineNo);
this.pnl_QueryBar.Controls.Add(this.lbl_EngineNo);
this.pnl_QueryBar.Controls.Add(this.dtp_End);
this.pnl_QueryBar.Controls.Add(this.lbl_DateTo);
this.pnl_QueryBar.Controls.Add(this.dtp_Start);
this.pnl_QueryBar.Controls.Add(this.lbl_DateFrom);
this.pnl_QueryBar.Dock = System.Windows.Forms.DockStyle.Top;
this.pnl_QueryBar.Height = 56;
this.pnl_QueryBar.Name = "pnl_QueryBar";
this.pnl_QueryBar.Padding = new System.Windows.Forms.Padding(16, 12, 16, 12);
// 日期范围
this.lbl_DateFrom.AutoSize = true;
this.lbl_DateFrom.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lbl_DateFrom.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_DateFrom.Location = new System.Drawing.Point(16, 17);
this.lbl_DateFrom.Name = "lbl_DateFrom";
this.lbl_DateFrom.Text = "从";
this.dtp_Start.Font = new System.Drawing.Font("微软雅黑", 10F);
this.dtp_Start.Format = System.Windows.Forms.DateTimePickerFormat.Short;
this.dtp_Start.Location = new System.Drawing.Point(40, 13);
this.dtp_Start.Name = "dtp_Start";
this.dtp_Start.Size = new System.Drawing.Size(130, 25);
this.lbl_DateTo.AutoSize = true;
this.lbl_DateTo.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lbl_DateTo.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_DateTo.Location = new System.Drawing.Point(178, 17);
this.lbl_DateTo.Name = "lbl_DateTo";
this.lbl_DateTo.Text = "到";
this.dtp_End.Font = new System.Drawing.Font("微软雅黑", 10F);
this.dtp_End.Format = System.Windows.Forms.DateTimePickerFormat.Short;
this.dtp_End.Location = new System.Drawing.Point(200, 13);
this.dtp_End.Name = "dtp_End";
this.dtp_End.Size = new System.Drawing.Size(130, 25);
// 发动机号
this.lbl_EngineNo.AutoSize = true;
this.lbl_EngineNo.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lbl_EngineNo.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_EngineNo.Location = new System.Drawing.Point(360, 17);
this.lbl_EngineNo.Name = "lbl_EngineNo";
this.lbl_EngineNo.Text = "发动机号";
this.txt_EngineNo.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txt_EngineNo.Font = new System.Drawing.Font("微软雅黑", 10F);
this.txt_EngineNo.Location = new System.Drawing.Point(430, 13);
this.txt_EngineNo.Name = "txt_EngineNo";
this.txt_EngineNo.Size = new System.Drawing.Size(160, 25);
// 机型号
this.lbl_ModelNo.AutoSize = true;
this.lbl_ModelNo.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lbl_ModelNo.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_ModelNo.Location = new System.Drawing.Point(610, 17);
this.lbl_ModelNo.Name = "lbl_ModelNo";
this.lbl_ModelNo.Text = "机型号";
this.txt_ModelNo.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txt_ModelNo.Font = new System.Drawing.Font("微软雅黑", 10F);
this.txt_ModelNo.Location = new System.Drawing.Point(666, 13);
this.txt_ModelNo.Name = "txt_ModelNo";
this.txt_ModelNo.Size = new System.Drawing.Size(160, 25);
// btn_Query
this.btn_Query.BackColor = System.Drawing.Color.FromArgb(74, 144, 217);
this.btn_Query.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Query.FlatAppearance.BorderSize = 0;
this.btn_Query.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Query.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Query.ForeColor = System.Drawing.Color.White;
this.btn_Query.Location = new System.Drawing.Point(850, 12);
this.btn_Query.Name = "btn_Query";
this.btn_Query.Size = new System.Drawing.Size(88, 30);
this.btn_Query.Text = "🔍 查询";
this.btn_Query.UseVisualStyleBackColor = false;
this.btn_Query.Click += new System.EventHandler(this.btn_Query_Click);
// btn_Export — 导出Excel
this.btn_Export.BackColor = System.Drawing.Color.FromArgb(5, 150, 105);
this.btn_Export.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Export.FlatAppearance.BorderSize = 0;
this.btn_Export.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Export.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Export.ForeColor = System.Drawing.Color.White;
this.btn_Export.Location = new System.Drawing.Point(950, 12);
this.btn_Export.Name = "btn_Export";
this.btn_Export.Size = new System.Drawing.Size(104, 30);
this.btn_Export.Text = "📥 导出 Excel";
this.btn_Export.UseVisualStyleBackColor = false;
this.btn_Export.Click += new System.EventHandler(this.btn_Export_Click);
// dgv_Data
this.dgv_Data.AllowUserToAddRows = false;
this.dgv_Data.AllowUserToDeleteRows = false;
this.dgv_Data.AllowUserToResizeRows = false;
this.dgv_Data.BackgroundColor = System.Drawing.Color.White;
this.dgv_Data.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.dgv_Data.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.SingleHorizontal;
this.dgv_Data.ColumnHeadersHeight = 42;
this.dgv_Data.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
this.dgv_Data.ColumnHeadersDefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(232, 237, 242);
this.dgv_Data.ColumnHeadersDefaultCellStyle.ForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
this.dgv_Data.ColumnHeadersDefaultCellStyle.Font = new System.Drawing.Font("微软雅黑", 11F, System.Drawing.FontStyle.Bold);
this.dgv_Data.DefaultCellStyle.ForeColor = System.Drawing.Color.FromArgb(31, 41, 55);
this.dgv_Data.DefaultCellStyle.Font = new System.Drawing.Font("微软雅黑", 11F);
this.dgv_Data.DefaultCellStyle.SelectionBackColor = System.Drawing.Color.FromArgb(219, 234, 254);
this.dgv_Data.DefaultCellStyle.SelectionForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
this.dgv_Data.AlternatingRowsDefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(248, 250, 252);
this.dgv_Data.Dock = System.Windows.Forms.DockStyle.Fill;
this.dgv_Data.EnableHeadersVisualStyles = false;
this.dgv_Data.GridColor = System.Drawing.Color.FromArgb(229, 231, 235);
this.dgv_Data.MultiSelect = false;
this.dgv_Data.Name = "dgv_Data";
this.dgv_Data.ReadOnly = true;
this.dgv_Data.RowHeadersVisible = false;
this.dgv_Data.RowTemplate.Height = 38;
this.dgv_Data.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.dgv_Data.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
// pnl_StatusBar
this.pnl_StatusBar.BackColor = System.Drawing.Color.White;
this.pnl_StatusBar.Dock = System.Windows.Forms.DockStyle.Bottom;
this.pnl_StatusBar.Height = 40;
this.pnl_StatusBar.Name = "pnl_StatusBar";
// UC_StationRecord
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.Color.FromArgb(245, 247, 250);
this.Controls.Add(this.dgv_Data);
this.Controls.Add(this.pnl_StatusBar);
this.Controls.Add(this.pnl_QueryBar);
this.Name = "UC_StationRecord";
this.Size = new System.Drawing.Size(1820, 1000);
this.pnl_QueryBar.ResumeLayout(false);
this.pnl_QueryBar.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dgv_Data)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel pnl_QueryBar;
private System.Windows.Forms.Label lbl_DateFrom;
private System.Windows.Forms.DateTimePicker dtp_Start;
private System.Windows.Forms.Label lbl_DateTo;
private System.Windows.Forms.DateTimePicker dtp_End;
private System.Windows.Forms.Label lbl_EngineNo;
private System.Windows.Forms.TextBox txt_EngineNo;
private System.Windows.Forms.Label lbl_ModelNo;
private System.Windows.Forms.TextBox txt_ModelNo;
private System.Windows.Forms.Button btn_Query;
private System.Windows.Forms.Button btn_Export;
private System.Windows.Forms.DataGridView dgv_Data;
private System.Windows.Forms.Panel pnl_StatusBar;
}
}

View File

@@ -0,0 +1,140 @@
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
namespace MesWork.Pages
{
/// <summary>
/// 过站记录查询页面 — 每个产品经过每个工位的明细记录
/// 对应存储过程过站记录_分页查询
/// </summary>
public partial class UC_StationRecord : UserControl
{
private PagerBar _pager;
public UC_StationRecord()
{
InitializeComponent();
InitColumns();
dtp_Start.Value = DateTime.Today.AddDays(-7);
dtp_End.Value = DateTime.Today;
_pager = new PagerBar();
_pager.PageChanged += (s, e) => LoadData();
this.Controls.Remove(pnl_StatusBar);
this.Controls.Add(_pager);
this.Controls.SetChildIndex(_pager, this.Controls.Count - 2);
}
private void InitColumns()
{
dgv_Data.AutoGenerateColumns = false;
dgv_Data.Columns.Clear();
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "ID", HeaderText = "ID", DataPropertyName = "ID", Visible = false });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "发动机号", HeaderText = "发动机号", DataPropertyName = "发动机号", FillWeight = 100 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "机型号", HeaderText = "机型号", DataPropertyName = "机型号", FillWeight = 70 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "工单号", HeaderText = "订单号", DataPropertyName = "工单号", FillWeight = 80 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "工位号", HeaderText = "工位号", DataPropertyName = "工位号", FillWeight = 60 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "工位名称", HeaderText = "工位名称", DataPropertyName = "工位名称", FillWeight = 70 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "到站时间", HeaderText = "到达时间", DataPropertyName = "到站时间", FillWeight = 110,
DefaultCellStyle = new DataGridViewCellStyle { Format = "yyyy/MM/dd HH:mm:ss" } });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "离站时间", HeaderText = "离开时间", DataPropertyName = "离站时间", FillWeight = 110,
DefaultCellStyle = new DataGridViewCellStyle { Format = "yyyy/MM/dd HH:mm:ss" } });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "停站时间", HeaderText = "在位(秒)", DataPropertyName = "停站时间", FillWeight = 55 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "称重重量", HeaderText = "称重重量(kg)", DataPropertyName = "称重重量", FillWeight = 80 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "加油量", HeaderText = "加油量", DataPropertyName = "加油量", FillWeight = 60 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "抽油量", HeaderText = "抽油量", DataPropertyName = "抽油量", FillWeight = 60 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "油密度", HeaderText = "油密度", DataPropertyName = "油密度", FillWeight = 60 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "操作者", HeaderText = "操作员", DataPropertyName = "操作者", FillWeight = 60 });
}
private void btn_Query_Click(object sender, EventArgs e)
{
_pager.ResetPage();
LoadData();
}
private void LoadData()
{
try
{
var (pageCountParam, itemCountParam) = PagerBar.CreateOutputParams();
var parms = new SqlParameter[]
{
new SqlParameter("@发动机号", txt_EngineNo.Text.Trim()),
new SqlParameter("@机型号", txt_ModelNo.Text.Trim()),
new SqlParameter("@开始时间", dtp_Start.Value.ToString("yyyy-MM-dd")),
new SqlParameter("@结束时间", dtp_End.Value.AddDays(1).ToString("yyyy-MM-dd")),
new SqlParameter("@PageCurrent", _pager.CurrentPage),
new SqlParameter("@PageSize", _pager.PageSize),
pageCountParam,
itemCountParam
};
SqlOperation.ExecuteStoredProcedure("过站记录_分页查询", parms, out DataTable dt, out string err);
if (dt != null) dgv_Data.DataSource = dt;
_pager.UpdateState(pageCountParam, itemCountParam);
}
catch (Exception ex)
{
MessageBox.Show($"查询失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void btn_Export_Click(object sender, EventArgs e)
{
if (dgv_Data.Rows.Count == 0)
{
MessageBox.Show("没有数据可导出,请先查询", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
using (var sfd = new SaveFileDialog())
{
sfd.Filter = "Excel 文件|*.xlsx";
sfd.FileName = $"过站记录_{DateTime.Now:yyyyMMdd_HHmmss}.xlsx";
sfd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
if (sfd.ShowDialog() == DialogResult.OK)
{
try
{
// 用当前查询条件重新查询全量数据(不受分页限制)
var (pageCountParam, itemCountParam) = PagerBar.CreateOutputParams();
var parms = new SqlParameter[]
{
new SqlParameter("@发动机号", txt_EngineNo.Text.Trim()),
new SqlParameter("@机型号", txt_ModelNo.Text.Trim()),
new SqlParameter("@开始时间", dtp_Start.Value.ToString("yyyy-MM-dd")),
new SqlParameter("@结束时间", dtp_End.Value.AddDays(1).ToString("yyyy-MM-dd")),
new SqlParameter("@PageCurrent", 1),
new SqlParameter("@PageSize", 9999999),
pageCountParam,
itemCountParam
};
SqlOperation.ExecuteStoredProcedure("过站记录_分页查询", parms, out DataTable dt, out string err);
if (dt != null && dt.Rows.Count > 0)
{
bool exported = NPOITest.ExeclHelper.DataTableToExcel(dt, "过站记录", sfd.FileName);
if (exported)
{
MessageBox.Show($"导出成功!共 {dt.Rows.Count} 条记录", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{sfd.FileName}\"");
}
else
{
MessageBox.Show("导出失败,请检查文件是否被占用", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
MessageBox.Show("查询全量数据失败,请重试", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
catch (Exception ex)
{
MessageBox.Show($"导出失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
}
}

310
SCADA/Pages/UC_Statistics.Designer.cs generated Normal file
View File

@@ -0,0 +1,310 @@
namespace MesWork.Pages
{
partial class UC_Statistics
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
components.Dispose();
base.Dispose(disposing);
}
#region
private void InitializeComponent()
{
this.pnl_QueryBar = new System.Windows.Forms.Panel();
this.lbl_DateFrom = new System.Windows.Forms.Label();
this.dtp_Start = new System.Windows.Forms.DateTimePicker();
this.lbl_DateTo = new System.Windows.Forms.Label();
this.dtp_End = new System.Windows.Forms.DateTimePicker();
this.txt_ModelNo = new System.Windows.Forms.TextBox();
this.txt_OrderNo = new System.Windows.Forms.TextBox();
this.btn_Analyze = new System.Windows.Forms.Button();
this.btn_Export = new System.Windows.Forms.Button();
this.pnl_ChartArea = new System.Windows.Forms.Panel();
this.pnl_Chart = new System.Windows.Forms.Panel();
this.lbl_ChartTitle = new System.Windows.Forms.Label();
this.pnl_StatsCard = new System.Windows.Forms.Panel();
this.lbl_StatsTitle = new System.Windows.Forms.Label();
this.lbl_StatMax = new System.Windows.Forms.Label();
this.lbl_StatMin = new System.Windows.Forms.Label();
this.lbl_StatAvg = new System.Windows.Forms.Label();
this.lbl_StatMedian = new System.Windows.Forms.Label();
this.lbl_StatRange = new System.Windows.Forms.Label();
this.lbl_StatVariance = new System.Windows.Forms.Label();
this.lbl_StatStdDev = new System.Windows.Forms.Label();
this.lbl_StatCount = new System.Windows.Forms.Label();
this.dgv_Data = new System.Windows.Forms.DataGridView();
this.pnl_QueryBar.SuspendLayout();
this.pnl_ChartArea.SuspendLayout();
this.pnl_Chart.SuspendLayout();
this.pnl_StatsCard.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dgv_Data)).BeginInit();
this.SuspendLayout();
//
// pnl_QueryBar — 查询栏(增高,两行布局)
//
this.pnl_QueryBar.BackColor = System.Drawing.Color.White;
this.pnl_QueryBar.Controls.Add(this.btn_Export);
this.pnl_QueryBar.Controls.Add(this.btn_Analyze);
this.pnl_QueryBar.Controls.Add(this.txt_OrderNo);
this.pnl_QueryBar.Controls.Add(this.txt_ModelNo);
this.pnl_QueryBar.Controls.Add(this.dtp_End);
this.pnl_QueryBar.Controls.Add(this.lbl_DateTo);
this.pnl_QueryBar.Controls.Add(this.dtp_Start);
this.pnl_QueryBar.Controls.Add(this.lbl_DateFrom);
this.pnl_QueryBar.Dock = System.Windows.Forms.DockStyle.Top;
this.pnl_QueryBar.Height = 56;
this.pnl_QueryBar.Name = "pnl_QueryBar";
this.pnl_QueryBar.Padding = new System.Windows.Forms.Padding(16, 0, 16, 0);
//
// lbl_DateFrom
//
this.lbl_DateFrom.AutoSize = true;
this.lbl_DateFrom.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lbl_DateFrom.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_DateFrom.Location = new System.Drawing.Point(16, 17);
this.lbl_DateFrom.Name = "lbl_DateFrom";
this.lbl_DateFrom.Text = "从";
//
// dtp_Start
//
this.dtp_Start.Font = new System.Drawing.Font("微软雅黑", 10F);
this.dtp_Start.Format = System.Windows.Forms.DateTimePickerFormat.Short;
this.dtp_Start.Location = new System.Drawing.Point(40, 13);
this.dtp_Start.Name = "dtp_Start";
this.dtp_Start.Size = new System.Drawing.Size(130, 25);
//
// lbl_DateTo
//
this.lbl_DateTo.AutoSize = true;
this.lbl_DateTo.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lbl_DateTo.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_DateTo.Location = new System.Drawing.Point(178, 17);
this.lbl_DateTo.Name = "lbl_DateTo";
this.lbl_DateTo.Text = "到";
//
// dtp_End
//
this.dtp_End.Font = new System.Drawing.Font("微软雅黑", 10F);
this.dtp_End.Format = System.Windows.Forms.DateTimePickerFormat.Short;
this.dtp_End.Location = new System.Drawing.Point(200, 13);
this.dtp_End.Name = "dtp_End";
this.dtp_End.Size = new System.Drawing.Size(130, 25);
//
// txt_ModelNo — 机型号筛选
//
this.txt_ModelNo.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txt_ModelNo.Font = new System.Drawing.Font("微软雅黑", 10F);
this.txt_ModelNo.Location = new System.Drawing.Point(350, 13);
this.txt_ModelNo.Name = "txt_ModelNo";
this.txt_ModelNo.Size = new System.Drawing.Size(140, 27);
//
// txt_OrderNo — 订单号筛选
//
this.txt_OrderNo.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txt_OrderNo.Font = new System.Drawing.Font("微软雅黑", 10F);
this.txt_OrderNo.Location = new System.Drawing.Point(500, 13);
this.txt_OrderNo.Name = "txt_OrderNo";
this.txt_OrderNo.Size = new System.Drawing.Size(140, 27);
//
// btn_Analyze — 统计分析按钮
//
this.btn_Analyze.BackColor = System.Drawing.Color.FromArgb(74, 144, 217);
this.btn_Analyze.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Analyze.FlatAppearance.BorderSize = 0;
this.btn_Analyze.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Analyze.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Analyze.ForeColor = System.Drawing.Color.White;
this.btn_Analyze.Location = new System.Drawing.Point(660, 12);
this.btn_Analyze.Name = "btn_Analyze";
this.btn_Analyze.Size = new System.Drawing.Size(110, 30);
this.btn_Analyze.Text = "📊 统计分析";
this.btn_Analyze.UseVisualStyleBackColor = false;
this.btn_Analyze.Click += new System.EventHandler(this.btn_Analyze_Click);
//
// btn_Export — 导出数据按钮
//
this.btn_Export.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
this.btn_Export.BackColor = System.Drawing.Color.FromArgb(5, 150, 105);
this.btn_Export.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Export.FlatAppearance.BorderSize = 0;
this.btn_Export.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Export.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Export.ForeColor = System.Drawing.Color.White;
this.btn_Export.Location = new System.Drawing.Point(1700, 12);
this.btn_Export.Name = "btn_Export";
this.btn_Export.Size = new System.Drawing.Size(104, 30);
this.btn_Export.Text = "📥 导出数据";
this.btn_Export.UseVisualStyleBackColor = false;
this.btn_Export.Click += new System.EventHandler(this.btn_Export_Click);
//
// pnl_ChartArea — 图表+统计卡片区域
//
this.pnl_ChartArea.Dock = System.Windows.Forms.DockStyle.Top;
this.pnl_ChartArea.Height = 400;
this.pnl_ChartArea.Name = "pnl_ChartArea";
this.pnl_ChartArea.Padding = new System.Windows.Forms.Padding(12, 8, 12, 8);
this.pnl_ChartArea.Controls.Add(this.pnl_Chart);
this.pnl_ChartArea.Controls.Add(this.pnl_StatsCard);
//
// pnl_Chart — 图表区域
//
this.pnl_Chart.BackColor = System.Drawing.Color.White;
this.pnl_Chart.Dock = System.Windows.Forms.DockStyle.Fill;
this.pnl_Chart.Name = "pnl_Chart";
this.pnl_Chart.Padding = new System.Windows.Forms.Padding(16, 8, 16, 8);
this.pnl_Chart.Controls.Add(this.lbl_ChartTitle);
//
// lbl_ChartTitle
//
this.lbl_ChartTitle.Dock = System.Windows.Forms.DockStyle.Top;
this.lbl_ChartTitle.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold);
this.lbl_ChartTitle.ForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
this.lbl_ChartTitle.Height = 32;
this.lbl_ChartTitle.Name = "lbl_ChartTitle";
this.lbl_ChartTitle.Text = "📈 机油残留量趋势分析";
this.lbl_ChartTitle.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// pnl_StatsCard — 右侧统计指标卡片
//
this.pnl_StatsCard.BackColor = System.Drawing.Color.FromArgb(248, 250, 252);
this.pnl_StatsCard.Dock = System.Windows.Forms.DockStyle.Right;
this.pnl_StatsCard.Width = 260;
this.pnl_StatsCard.Name = "pnl_StatsCard";
this.pnl_StatsCard.Padding = new System.Windows.Forms.Padding(20, 8, 20, 8);
this.pnl_StatsCard.Controls.Add(this.lbl_StatCount);
this.pnl_StatsCard.Controls.Add(this.lbl_StatStdDev);
this.pnl_StatsCard.Controls.Add(this.lbl_StatVariance);
this.pnl_StatsCard.Controls.Add(this.lbl_StatRange);
this.pnl_StatsCard.Controls.Add(this.lbl_StatMedian);
this.pnl_StatsCard.Controls.Add(this.lbl_StatAvg);
this.pnl_StatsCard.Controls.Add(this.lbl_StatMin);
this.pnl_StatsCard.Controls.Add(this.lbl_StatMax);
this.pnl_StatsCard.Controls.Add(this.lbl_StatsTitle);
//
// lbl_StatsTitle
//
this.lbl_StatsTitle.Dock = System.Windows.Forms.DockStyle.Top;
this.lbl_StatsTitle.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold);
this.lbl_StatsTitle.ForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
this.lbl_StatsTitle.Height = 36;
this.lbl_StatsTitle.Name = "lbl_StatsTitle";
this.lbl_StatsTitle.Text = "📋 统计指标";
this.lbl_StatsTitle.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// 统计数值标签
//
this.lbl_StatMax.AutoSize = true; this.lbl_StatMax.Font = new System.Drawing.Font("微软雅黑", 10.5F);
this.lbl_StatMax.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_StatMax.Location = new System.Drawing.Point(20, 50); this.lbl_StatMax.Name = "lbl_StatMax"; this.lbl_StatMax.Text = "最大值 —";
this.lbl_StatMin.AutoSize = true; this.lbl_StatMin.Font = new System.Drawing.Font("微软雅黑", 10.5F);
this.lbl_StatMin.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_StatMin.Location = new System.Drawing.Point(20, 82); this.lbl_StatMin.Name = "lbl_StatMin"; this.lbl_StatMin.Text = "最小值 —";
this.lbl_StatAvg.AutoSize = true; this.lbl_StatAvg.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Bold);
this.lbl_StatAvg.ForeColor = System.Drawing.Color.FromArgb(245, 158, 11);
this.lbl_StatAvg.Location = new System.Drawing.Point(20, 114); this.lbl_StatAvg.Name = "lbl_StatAvg"; this.lbl_StatAvg.Text = "平均值 —";
this.lbl_StatMedian.AutoSize = true; this.lbl_StatMedian.Font = new System.Drawing.Font("微软雅黑", 10.5F);
this.lbl_StatMedian.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_StatMedian.Location = new System.Drawing.Point(20, 146); this.lbl_StatMedian.Name = "lbl_StatMedian"; this.lbl_StatMedian.Text = "中位数 —";
this.lbl_StatRange.AutoSize = true; this.lbl_StatRange.Font = new System.Drawing.Font("微软雅黑", 10.5F);
this.lbl_StatRange.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_StatRange.Location = new System.Drawing.Point(20, 178); this.lbl_StatRange.Name = "lbl_StatRange"; this.lbl_StatRange.Text = "极差 —";
this.lbl_StatVariance.AutoSize = true; this.lbl_StatVariance.Font = new System.Drawing.Font("微软雅黑", 10.5F);
this.lbl_StatVariance.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_StatVariance.Location = new System.Drawing.Point(20, 210); this.lbl_StatVariance.Name = "lbl_StatVariance"; this.lbl_StatVariance.Text = "方差 —";
this.lbl_StatStdDev.AutoSize = true; this.lbl_StatStdDev.Font = new System.Drawing.Font("微软雅黑", 10.5F);
this.lbl_StatStdDev.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_StatStdDev.Location = new System.Drawing.Point(20, 242); this.lbl_StatStdDev.Name = "lbl_StatStdDev"; this.lbl_StatStdDev.Text = "标准差 —";
this.lbl_StatCount.AutoSize = true; this.lbl_StatCount.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Bold);
this.lbl_StatCount.ForeColor = System.Drawing.Color.FromArgb(74, 144, 217);
this.lbl_StatCount.Location = new System.Drawing.Point(20, 282); this.lbl_StatCount.Name = "lbl_StatCount"; this.lbl_StatCount.Text = "样本数 0";
//
// dgv_Data — 明细表
//
this.dgv_Data.AllowUserToAddRows = false;
this.dgv_Data.AllowUserToDeleteRows = false;
this.dgv_Data.AllowUserToResizeRows = false;
this.dgv_Data.BackgroundColor = System.Drawing.Color.White;
this.dgv_Data.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.dgv_Data.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.SingleHorizontal;
this.dgv_Data.ColumnHeadersHeight = 40;
this.dgv_Data.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
this.dgv_Data.ColumnHeadersDefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(232, 237, 242);
this.dgv_Data.ColumnHeadersDefaultCellStyle.ForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
this.dgv_Data.ColumnHeadersDefaultCellStyle.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.dgv_Data.ColumnHeadersDefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
this.dgv_Data.DefaultCellStyle.ForeColor = System.Drawing.Color.FromArgb(31, 41, 55);
this.dgv_Data.DefaultCellStyle.Font = new System.Drawing.Font("微软雅黑", 10F);
this.dgv_Data.DefaultCellStyle.SelectionBackColor = System.Drawing.Color.FromArgb(219, 234, 254);
this.dgv_Data.DefaultCellStyle.SelectionForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
this.dgv_Data.DefaultCellStyle.Padding = new System.Windows.Forms.Padding(6, 0, 6, 0);
this.dgv_Data.AlternatingRowsDefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(248, 250, 252);
this.dgv_Data.Dock = System.Windows.Forms.DockStyle.Fill;
this.dgv_Data.EnableHeadersVisualStyles = false;
this.dgv_Data.GridColor = System.Drawing.Color.FromArgb(229, 231, 235);
this.dgv_Data.MultiSelect = false;
this.dgv_Data.Name = "dgv_Data";
this.dgv_Data.ReadOnly = true;
this.dgv_Data.RowHeadersVisible = false;
this.dgv_Data.RowTemplate.Height = 36;
this.dgv_Data.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.dgv_Data.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
//
// UC_Statistics
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.Color.FromArgb(245, 247, 250);
this.Controls.Add(this.dgv_Data);
this.Controls.Add(this.pnl_ChartArea);
this.Controls.Add(this.pnl_QueryBar);
this.Name = "UC_Statistics";
this.Size = new System.Drawing.Size(1820, 1000);
this.pnl_QueryBar.ResumeLayout(false);
this.pnl_QueryBar.PerformLayout();
this.pnl_ChartArea.ResumeLayout(false);
this.pnl_Chart.ResumeLayout(false);
this.pnl_StatsCard.ResumeLayout(false);
this.pnl_StatsCard.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dgv_Data)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel pnl_QueryBar;
private System.Windows.Forms.Label lbl_DateFrom;
private System.Windows.Forms.DateTimePicker dtp_Start;
private System.Windows.Forms.Label lbl_DateTo;
private System.Windows.Forms.DateTimePicker dtp_End;
private System.Windows.Forms.TextBox txt_ModelNo;
private System.Windows.Forms.TextBox txt_OrderNo;
private System.Windows.Forms.Button btn_Analyze;
private System.Windows.Forms.Button btn_Export;
private System.Windows.Forms.Panel pnl_ChartArea;
private System.Windows.Forms.Panel pnl_Chart;
private System.Windows.Forms.Label lbl_ChartTitle;
private System.Windows.Forms.Panel pnl_StatsCard;
private System.Windows.Forms.Label lbl_StatsTitle;
private System.Windows.Forms.Label lbl_StatMax;
private System.Windows.Forms.Label lbl_StatMin;
private System.Windows.Forms.Label lbl_StatAvg;
private System.Windows.Forms.Label lbl_StatMedian;
private System.Windows.Forms.Label lbl_StatRange;
private System.Windows.Forms.Label lbl_StatVariance;
private System.Windows.Forms.Label lbl_StatStdDev;
private System.Windows.Forms.Label lbl_StatCount;
private System.Windows.Forms.DataGridView dgv_Data;
}
}

View File

@@ -0,0 +1,471 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Windows.Forms;
namespace MesWork.Pages
{
/// <summary>
/// 统计分析页面 — 残留量趋势分析 + 统计指标计算 + 明细数据
/// 使用 GDI+ 绘制趋势折线图(含平均线 + 数据标签)
/// </summary>
public partial class UC_Statistics : UserControl
{
/// <summary>图表数据缓存</summary>
private List<(DateTime time, double value, string label)> _chartData = new List<(DateTime, double, string)>();
/// <summary>平均值(用于绘制参考线)</summary>
private double _avgValue = 0;
// ─── 配色常量 ───
private static readonly Color CLR_PRIMARY = Color.FromArgb(74, 144, 217);
private static readonly Color CLR_PRIMARY_DARK = Color.FromArgb(30, 58, 95);
private static readonly Color CLR_AVG_LINE = Color.FromArgb(245, 158, 11); // 橙色平均线
private static readonly Color CLR_GRID = Color.FromArgb(236, 239, 243);
private static readonly Color CLR_TEXT = Color.FromArgb(55, 65, 81);
private static readonly Color CLR_TEXT_LIGHT = Color.FromArgb(107, 114, 128);
private static readonly Color CLR_DOT_FILL = Color.FromArgb(74, 144, 217);
private static readonly Color CLR_CARD_BG = Color.FromArgb(248, 250, 252);
public UC_Statistics()
{
InitializeComponent();
InitColumns();
dtp_Start.Value = DateTime.Today.AddDays(-30);
dtp_End.Value = DateTime.Today;
// 订阅图表区域绘制
pnl_Chart.Paint += pnl_Chart_Paint;
pnl_Chart.Resize += (s, ev) => pnl_Chart.Invalidate();
// 为筛选框加占位提示
SetHint(txt_ModelNo, "机型号筛选...");
SetHint(txt_OrderNo, "订单号筛选...");
}
private void SetHint(TextBox txt, string hint)
{
txt.Tag = hint;
txt.Text = hint;
txt.ForeColor = Color.FromArgb(156, 163, 175);
txt.GotFocus += (s, e) => { if (txt.Text == hint) { txt.Text = ""; txt.ForeColor = CLR_PRIMARY_DARK; } };
txt.LostFocus += (s, e) => { if (string.IsNullOrWhiteSpace(txt.Text)) { txt.Text = hint; txt.ForeColor = Color.FromArgb(156, 163, 175); } };
}
private string GetHintValue(TextBox txt)
{
return txt.Text == txt.Tag?.ToString() ? "" : txt.Text.Trim();
}
/// <summary>
/// 预设明细表格列
/// </summary>
private void InitColumns()
{
dgv_Data.AutoGenerateColumns = false;
dgv_Data.Columns.Clear();
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "序号", HeaderText = "序号", Width = 50, FillWeight = 30 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "ID", HeaderText = "ID", DataPropertyName = "ID", Visible = false });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "测试时间", HeaderText = "检测时间", DataPropertyName = "测试时间", FillWeight = 100 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "发动机号", HeaderText = "工件编号", DataPropertyName = "发动机号", FillWeight = 100 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "订单号", HeaderText = "订单号", DataPropertyName = "订单号", FillWeight = 80 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "机型号", HeaderText = "机型号", DataPropertyName = "机型号", FillWeight = 70 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "残留量", HeaderText = "机油残留(mg)", DataPropertyName = "残留量", FillWeight = 80 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "设备编号", HeaderText = "设备编号", DataPropertyName = "设备编号", FillWeight = 60 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "操作员", HeaderText = "操作员", DataPropertyName = "操作员", FillWeight = 60 });
}
/// <summary>
/// 统计分析按钮
/// </summary>
private void btn_Analyze_Click(object sender, EventArgs e)
{
try
{
var pageCountParam = new SqlParameter("@PageCount", SqlDbType.Int) { Direction = ParameterDirection.Output };
var itemCountParam = new SqlParameter("@ItemCount", SqlDbType.Int) { Direction = ParameterDirection.Output };
var parms = new SqlParameter[]
{
new SqlParameter("@发动机号", ""),
new SqlParameter("@机型号", GetHintValue(txt_ModelNo)),
new SqlParameter("@工单号", GetHintValue(txt_OrderNo)),
new SqlParameter("@开始时间", dtp_Start.Value.ToString("yyyy-MM-dd")),
new SqlParameter("@结束时间", dtp_End.Value.AddDays(1).ToString("yyyy-MM-dd")),
new SqlParameter("@PageCurrent", 1),
new SqlParameter("@PageSize", 9999),
pageCountParam,
itemCountParam
};
SqlOperation.ExecuteStoredProcedure("称重记录_分页查询", parms, out DataTable dt, out string err);
if (dt != null && dt.Rows.Count > 0)
{
dgv_Data.DataSource = dt;
FillRowNumbers();
CalculateStatistics(dt);
BuildChartData(dt);
pnl_Chart.Invalidate();
}
else
{
_chartData.Clear();
ClearStatLabels();
pnl_Chart.Invalidate();
MessageBox.Show("查询范围内无数据", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception ex)
{
MessageBox.Show($"查询失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 填充表格序号列(与图表数据点编号对应)
/// 图表按时间升序排列表格按ID降序序号在数据排序后重新映射
/// </summary>
private void FillRowNumbers()
{
// 表格数据按ID降序排列最新在前序号直接按行号赋值
for (int i = 0; i < dgv_Data.Rows.Count; i++)
{
dgv_Data.Rows[i].Cells["序号"].Value = i + 1;
}
}
/// <summary>
/// 从DataTable构建图表数据确保所有行都被处理
/// </summary>
private void BuildChartData(DataTable dt)
{
_chartData.Clear();
// 查找时间列和数值列
string timeCol = dt.Columns.Contains("进站时间") ? "进站时间" :
dt.Columns.Contains("测试时间") ? "测试时间" : null;
string valCol = dt.Columns.Contains("残油量") ? "残油量" :
dt.Columns.Contains("残留量") ? "残留量" :
dt.Columns.Contains("放油量") ? "放油量" : null;
string labelCol = dt.Columns.Contains("发动机号") ? "发动机号" : null;
if (timeCol == null || valCol == null) return;
foreach (DataRow row in dt.Rows)
{
DateTime t;
double v;
string lbl = labelCol != null ? row[labelCol]?.ToString() ?? "" : "";
// 时间解析:如果失败则使用当前时间递增
if (!DateTime.TryParse(row[timeCol]?.ToString(), out t))
t = DateTime.Now;
// 数值解析如果失败或为空默认为0也是有效数据点
object rawVal = row[valCol];
if (rawVal == null || rawVal == DBNull.Value || !double.TryParse(rawVal.ToString(), out v))
v = 0;
_chartData.Add((t, v, lbl));
}
// 不排序保持DataTable原始行顺序与表格序号一致
}
/// <summary>
/// GDI+ 绘制折线图(增强版)
/// </summary>
private void pnl_Chart_Paint(object sender, PaintEventArgs e)
{
var g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
var rect = pnl_Chart.ClientRectangle;
int padL = 80, padR = 40, padT = 50, padB = 60;
int chartW = rect.Width - padL - padR;
int chartH = rect.Height - padT - padB;
if (chartW < 50 || chartH < 50) return;
// 绘制背景
using (var bgBrush = new SolidBrush(Color.White))
g.FillRectangle(bgBrush, rect);
// 空数据提示
if (_chartData.Count == 0)
{
using (var font = new Font("微软雅黑", 14F))
using (var brush = new SolidBrush(Color.FromArgb(156, 163, 175)))
{
var msg = "📊 设置筛选条件后点击「统计分析」查看趋势图";
var sz = g.MeasureString(msg, font);
g.DrawString(msg, font, brush, (rect.Width - sz.Width) / 2, (rect.Height - sz.Height) / 2);
}
return;
}
// 计算数据范围
double minVal = _chartData.Min(d => d.value);
double maxVal = _chartData.Max(d => d.value);
double range = maxVal - minVal;
if (range < 0.001) { range = Math.Max(Math.Abs(maxVal) * 0.2, 1); }
minVal -= range * 0.12;
maxVal += range * 0.12;
if (minVal < 0 && _chartData.Min(d => d.value) >= 0) minVal = 0; // 不让Y轴负数如果原始数据非负
int totalPts = _chartData.Count;
// ─── 绘制网格线和Y轴标签 ───
using (var gridPen = new Pen(CLR_GRID, 1) { DashStyle = DashStyle.Dot })
using (var axisFont = new Font("微软雅黑", 9F))
using (var axisBrush = new SolidBrush(CLR_TEXT_LIGHT))
using (var axisPen = new Pen(Color.FromArgb(200, 210, 220), 1))
{
// Y轴线
g.DrawLine(axisPen, padL, padT, padL, padT + chartH);
// X轴线
g.DrawLine(axisPen, padL, padT + chartH, padL + chartW, padT + chartH);
for (int i = 0; i <= 5; i++)
{
int y = padT + chartH - (int)(chartH * i / 5.0);
if (i > 0) g.DrawLine(gridPen, padL + 1, y, padL + chartW, y);
double val = minVal + (maxVal - minVal) * i / 5.0;
string valStr = val.ToString("F2");
var sz = g.MeasureString(valStr, axisFont);
g.DrawString(valStr, axisFont, axisBrush, padL - sz.Width - 6, y - sz.Height / 2);
}
// X轴标签 — 序号均匀排布1, 2, 3...
// 计算合适的标签间隔,避免过于密集
int maxLabels = Math.Max(1, chartW / 40); // 每个标签至少40px空间
int labelStep = Math.Max(1, (totalPts - 1) / Math.Max(maxLabels - 1, 1));
// 如果数据点少于maxLabels每个都显示
if (totalPts <= maxLabels) labelStep = 1;
for (int i = 0; i < totalPts; i += labelStep)
{
float xPos = totalPts == 1 ? padL + chartW / 2f
: padL + (float)chartW * i / (totalPts - 1);
string label = (i + 1).ToString();
var sz = g.MeasureString(label, axisFont);
g.DrawString(label, axisFont, axisBrush, xPos - sz.Width / 2, padT + chartH + 8);
g.DrawLine(axisPen, (int)xPos, padT + chartH, (int)xPos, padT + chartH + 5);
}
// 确保最后一个序号显示
if (totalPts > 1 && (totalPts - 1) % labelStep != 0)
{
float lastX = padL + chartW;
string lastLabel = totalPts.ToString();
var lastSz = g.MeasureString(lastLabel, axisFont);
g.DrawString(lastLabel, axisFont, axisBrush, lastX - lastSz.Width / 2, padT + chartH + 8);
g.DrawLine(axisPen, (int)lastX, padT + chartH, (int)lastX, padT + chartH + 5);
}
}
// ─── 计算所有数据点坐标X轴按序号均匀排布───
var points = new PointF[totalPts];
for (int i = 0; i < totalPts; i++)
{
float x = totalPts == 1 ? padL + chartW / 2f
: padL + (float)chartW * i / (totalPts - 1);
float y = padT + chartH - (float)(chartH * ((_chartData[i].value - minVal) / (maxVal - minVal)));
points[i] = new PointF(x, y);
}
// ─── 渐变填充区域 ───
if (points.Length >= 2)
{
using (var fillPath = new GraphicsPath())
{
fillPath.AddLines(points);
fillPath.AddLine(points.Last(), new PointF(points.Last().X, padT + chartH));
fillPath.AddLine(new PointF(points.Last().X, padT + chartH), new PointF(points.First().X, padT + chartH));
fillPath.CloseFigure();
using (var fillBrush = new LinearGradientBrush(
new Point(0, padT), new Point(0, padT + chartH),
Color.FromArgb(50, 74, 144, 217), Color.FromArgb(3, 74, 144, 217)))
{
g.FillPath(fillBrush, fillPath);
}
}
// 折线(粗线+阴影效果)
using (var shadowPen = new Pen(Color.FromArgb(30, 74, 144, 217), 5f))
{
shadowPen.LineJoin = LineJoin.Round;
g.DrawLines(shadowPen, points);
}
using (var linePen = new Pen(CLR_PRIMARY, 2.5f))
{
linePen.LineJoin = LineJoin.Round;
g.DrawLines(linePen, points);
}
}
// ─── 平均线(红色虚线 + 箭头 + 标签)───
if (_chartData.Count > 0)
{
float avgY = padT + chartH - (float)(chartH * ((_avgValue - minVal) / (maxVal - minVal)));
if (avgY >= padT && avgY <= padT + chartH)
{
using (var avgPen = new Pen(CLR_AVG_LINE, 1.8f) { DashStyle = DashStyle.Dash })
{
g.DrawLine(avgPen, padL, avgY, padL + chartW, avgY);
}
// 平均线标签(右侧带箭头标识)
using (var avgFont = new Font("微软雅黑", 9F, FontStyle.Bold))
using (var avgBrush = new SolidBrush(CLR_AVG_LINE))
{
string avgText = $"▶ 平均 {_avgValue:F2}";
var sz = g.MeasureString(avgText, avgFont);
// 背景
float lblX = padL + chartW - sz.Width - 4;
float lblY = avgY - sz.Height - 3;
using (var bgBrush = new SolidBrush(Color.FromArgb(220, 255, 255, 255)))
g.FillRectangle(bgBrush, lblX - 3, lblY, sz.Width + 6, sz.Height + 2);
g.DrawString(avgText, avgFont, avgBrush, lblX, lblY);
// 小三角箭头指向线
var arrowPts = new PointF[] {
new PointF(padL + chartW + 2, avgY),
new PointF(padL + chartW + 10, avgY - 5),
new PointF(padL + chartW + 10, avgY + 5)
};
g.FillPolygon(avgBrush, arrowPts);
}
}
}
// ─── 数据点(带光晕效果)───
for (int i = 0; i < points.Length; i++)
{
var pt = points[i];
// 光晕
using (var glowBrush = new SolidBrush(Color.FromArgb(40, 74, 144, 217)))
g.FillEllipse(glowBrush, pt.X - 8, pt.Y - 8, 16, 16);
// 白色底
g.FillEllipse(Brushes.White, pt.X - 5, pt.Y - 5, 10, 10);
// 蓝色圆点
using (var dotBrush = new SolidBrush(CLR_DOT_FILL))
g.FillEllipse(dotBrush, pt.X - 4, pt.Y - 4, 8, 8);
// 数值标签(只有当数据点不太密时显示)
if (_chartData.Count <= 15)
{
using (var valFont = new Font("微软雅黑", 8F))
using (var valBrush = new SolidBrush(CLR_PRIMARY_DARK))
{
string valText = _chartData[i].value.ToString("F1");
var sz = g.MeasureString(valText, valFont);
g.DrawString(valText, valFont, valBrush, pt.X - sz.Width / 2, pt.Y - sz.Height - 6);
}
}
}
// ─── 图表右下角水印 ───
using (var wmFont = new Font("微软雅黑", 8F))
using (var wmBrush = new SolidBrush(Color.FromArgb(80, 156, 163, 175)))
{
string wm = $"共 {_chartData.Count} 个样本";
var sz = g.MeasureString(wm, wmFont);
g.DrawString(wm, wmFont, wmBrush, padL + chartW - sz.Width, padT + 4);
}
}
/// <summary>
/// 计算统计指标(基于残留量列)
/// </summary>
private void CalculateStatistics(DataTable dt)
{
var values = new List<double>();
string colName = dt.Columns.Contains("残油量") ? "残油量" :
dt.Columns.Contains("残留量") ? "残留量" : null;
if (colName == null)
{
foreach (DataColumn col in dt.Columns)
{
if (col.ColumnName.Contains("残留") || col.ColumnName.Contains("残油") || col.ColumnName.Contains("重量"))
{
colName = col.ColumnName;
break;
}
}
}
if (colName != null)
{
foreach (DataRow row in dt.Rows)
{
object rawVal = row[colName];
if (rawVal != null && rawVal != DBNull.Value && double.TryParse(rawVal.ToString(), out double v))
values.Add(v);
else
values.Add(0); // 空值也算0确保样本数一致
}
}
if (values.Count == 0)
{
ClearStatLabels();
return;
}
values.Sort();
double max = values.Max();
double min = values.Min();
double avg = values.Average();
_avgValue = avg; // 保存平均值用于绘图
double median = values.Count % 2 == 0
? (values[values.Count / 2 - 1] + values[values.Count / 2]) / 2.0
: values[values.Count / 2];
double rangeVal = max - min;
double variance = values.Sum(v => Math.Pow(v - avg, 2)) / values.Count;
double stdDev = Math.Sqrt(variance);
// 更新统计指标标签
lbl_StatMax.Text = $"最大值 {max:F4}";
lbl_StatMin.Text = $"最小值 {min:F4}";
lbl_StatAvg.Text = $"平均值 {avg:F4}";
lbl_StatMedian.Text = $"中位数 {median:F4}";
lbl_StatRange.Text = $"极差 {rangeVal:F4}";
lbl_StatVariance.Text = $"方差 {variance:F4}";
lbl_StatStdDev.Text = $"标准差 {stdDev:F4}";
lbl_StatCount.Text = $"样本数 {values.Count}";
}
private void ClearStatLabels()
{
lbl_StatMax.Text = "最大值 —";
lbl_StatMin.Text = "最小值 —";
lbl_StatAvg.Text = "平均值 —";
lbl_StatMedian.Text = "中位数 —";
lbl_StatRange.Text = "极差 —";
lbl_StatVariance.Text = "方差 —";
lbl_StatStdDev.Text = "标准差 —";
lbl_StatCount.Text = "样本数 0";
}
/// <summary>
/// 导出数据
/// </summary>
private void btn_Export_Click(object sender, EventArgs e)
{
CrudHelper.ExportToExcel("统计分析", "统计分析", () =>
{
var (pageCountParam, itemCountParam) = PagerBar.CreateOutputParams();
var parms = new SqlParameter[]
{
new SqlParameter("@发动机号", ""),
new SqlParameter("@机型号", GetHintValue(txt_ModelNo)),
new SqlParameter("@工单号", GetHintValue(txt_OrderNo)),
new SqlParameter("@开始时间", dtp_Start.Value.ToString("yyyy-MM-dd")),
new SqlParameter("@结束时间", dtp_End.Value.AddDays(1).ToString("yyyy-MM-dd")),
new SqlParameter("@PageCurrent", 1),
new SqlParameter("@PageSize", 9999999),
pageCountParam, itemCountParam
};
SqlOperation.ExecuteStoredProcedure("称重记录_分页查询", parms, out DataTable dt, out string err);
return dt;
}, dgv_Data.Rows.Count > 0);
}
}
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata"><xsd:complexType><xsd:sequence><xsd:element name="value" type="xsd:string" minOccurs="0" /></xsd:sequence><xsd:attribute name="name" use="required" type="xsd:string" /><xsd:attribute name="type" type="xsd:string" /><xsd:attribute name="mimetype" type="xsd:string" /><xsd:attribute ref="xml:space" /></xsd:complexType></xsd:element>
<xsd:element name="assembly"><xsd:complexType><xsd:attribute name="alias" type="xsd:string" /><xsd:attribute name="name" type="xsd:string" /></xsd:complexType></xsd:element>
<xsd:element name="data"><xsd:complexType><xsd:sequence><xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /><xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /></xsd:sequence><xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /><xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /><xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /><xsd:attribute ref="xml:space" /></xsd:complexType></xsd:element>
<xsd:element name="resheader"><xsd:complexType><xsd:sequence><xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /></xsd:sequence><xsd:attribute name="name" type="xsd:string" use="required" /></xsd:complexType></xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype"><value>text/microsoft-resx</value></resheader>
<resheader name="version"><value>2.0</value></resheader>
<resheader name="reader"><value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader>
<resheader name="writer"><value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader>
</root>

View File

@@ -0,0 +1,93 @@
namespace MesWork.Pages
{
partial class UC_SystemSettings
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
components.Dispose();
base.Dispose(disposing);
}
#region
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.pnl_Header = new System.Windows.Forms.Panel();
this.lbl_Title = new System.Windows.Forms.Label();
this.grp_Scanner1 = new System.Windows.Forms.GroupBox();
this.grp_Scanner2 = new System.Windows.Forms.GroupBox();
this.timer_Refresh = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// pnl_Header
//
this.pnl_Header.BackColor = System.Drawing.Color.White;
this.pnl_Header.Dock = System.Windows.Forms.DockStyle.Top;
this.pnl_Header.Height = 56;
this.pnl_Header.Padding = new System.Windows.Forms.Padding(24, 0, 0, 0);
this.pnl_Header.Name = "pnl_Header";
this.pnl_Header.Controls.Add(this.lbl_Title);
//
// lbl_Title
//
this.lbl_Title.AutoSize = true;
this.lbl_Title.Font = new System.Drawing.Font("微软雅黑", 14F, System.Drawing.FontStyle.Bold);
this.lbl_Title.ForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
this.lbl_Title.Location = new System.Drawing.Point(24, 14);
this.lbl_Title.Name = "lbl_Title";
this.lbl_Title.Text = "系统设置";
//
// grp_Scanner1
//
this.grp_Scanner1.Font = new System.Drawing.Font("微软雅黑", 11F, System.Drawing.FontStyle.Bold);
this.grp_Scanner1.ForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
this.grp_Scanner1.Location = new System.Drawing.Point(30, 76);
this.grp_Scanner1.Name = "grp_Scanner1";
this.grp_Scanner1.Size = new System.Drawing.Size(700, 200);
this.grp_Scanner1.Text = " OP10 扫码枪 ";
//
// grp_Scanner2
//
this.grp_Scanner2.Font = new System.Drawing.Font("微软雅黑", 11F, System.Drawing.FontStyle.Bold);
this.grp_Scanner2.ForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
this.grp_Scanner2.Location = new System.Drawing.Point(30, 296);
this.grp_Scanner2.Name = "grp_Scanner2";
this.grp_Scanner2.Size = new System.Drawing.Size(700, 200);
this.grp_Scanner2.Text = " OP20 扫码枪 ";
//
// timer_Refresh
//
this.timer_Refresh.Interval = 1000;
this.timer_Refresh.Tick += new System.EventHandler(this.timer_Refresh_Tick);
//
// UC_SystemSettings
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.Color.FromArgb(245, 247, 250);
this.Controls.Add(this.grp_Scanner1);
this.Controls.Add(this.grp_Scanner2);
this.Controls.Add(this.pnl_Header);
this.Name = "UC_SystemSettings";
this.Size = new System.Drawing.Size(1820, 1000);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Panel pnl_Header;
private System.Windows.Forms.Label lbl_Title;
private System.Windows.Forms.GroupBox grp_Scanner1;
private System.Windows.Forms.GroupBox grp_Scanner2;
private System.Windows.Forms.Timer timer_Refresh;
}
}

View File

@@ -0,0 +1,238 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace MesWork.Pages
{
/// <summary>
/// 系统设置页面 — 扫码枪连接管理
/// </summary>
public partial class UC_SystemSettings : UserControl
{
// OP10 控件
private ComboBox cmb_Com1;
private Button btn_Connect1, btn_Disconnect1, btn_ManualSend1;
private Label lbl_Status1, lbl_ScanTime1;
private TextBox txt_Barcode1;
// OP20 控件
private ComboBox cmb_Com2;
private Button btn_Connect2, btn_Disconnect2, btn_ManualSend2;
private Label lbl_Status2, lbl_ScanTime2;
private TextBox txt_Barcode2;
public UC_SystemSettings()
{
InitializeComponent();
if (BarcodeManager.IsEnabled)
{
BuildScannerPanel(grp_Scanner1, "OP10", ref cmb_Com1, ref lbl_Status1, ref txt_Barcode1, ref lbl_ScanTime1,
ref btn_Connect1, ref btn_Disconnect1, ref btn_ManualSend1);
BuildScannerPanel(grp_Scanner2, "OP20", ref cmb_Com2, ref lbl_Status2, ref txt_Barcode2, ref lbl_ScanTime2,
ref btn_Connect2, ref btn_Disconnect2, ref btn_ManualSend2);
timer_Refresh.Start();
}
else
{
BuildScannerPanel(grp_Scanner1, "OP10", ref cmb_Com1, ref lbl_Status1, ref txt_Barcode1, ref lbl_ScanTime1,
ref btn_Connect1, ref btn_Disconnect1, ref btn_ManualSend1);
BuildScannerPanel(grp_Scanner2, "OP20", ref cmb_Com2, ref lbl_Status2, ref txt_Barcode2, ref lbl_ScanTime2,
ref btn_Connect2, ref btn_Disconnect2, ref btn_ManualSend2);
grp_Scanner1.Enabled = false;
grp_Scanner2.Enabled = false;
}
}
/// <summary>
/// 动态构建单个扫码枪面板的控件
/// </summary>
private void BuildScannerPanel(GroupBox grp, string opName,
ref ComboBox cmb, ref Label lblStatus, ref TextBox txtBar, ref Label lblTime,
ref Button btnConn, ref Button btnDisc, ref Button btnSend)
{
var normalFont = new Font("微软雅黑", 10F);
var boldFont = new Font("微软雅黑", 10F, FontStyle.Bold);
int y1 = 35, y2 = 75, y3 = 115;
// Row 1: COM口选择 + 连接/断开
var lblCom = new Label { Text = "COM口:", Font = normalFont, ForeColor = Color.FromArgb(55, 65, 81),
Location = new Point(20, y1 + 4), AutoSize = true };
grp.Controls.Add(lblCom);
cmb = new ComboBox { Font = normalFont, Location = new Point(90, y1), Size = new Size(110, 28),
DropDownStyle = ComboBoxStyle.DropDownList };
RefreshComPorts(cmb, opName);
grp.Controls.Add(cmb);
// 局部变量捕获ref参数不能在lambda中使用
var localCmb = cmb;
var localTxtBar = txtBar;
btnConn = new Button
{
Text = "🔗 连接", Font = boldFont, Size = new Size(90, 30), Location = new Point(215, y1 - 2),
BackColor = Color.FromArgb(74, 144, 217), ForeColor = Color.White,
FlatStyle = FlatStyle.Flat, Cursor = Cursors.Hand
};
btnConn.FlatAppearance.BorderSize = 0;
btnConn.Click += (s, e) => DoConnect(opName, localCmb);
grp.Controls.Add(btnConn);
btnDisc = new Button
{
Text = "⛔ 断开", Font = boldFont, Size = new Size(90, 30), Location = new Point(315, y1 - 2),
BackColor = Color.FromArgb(239, 68, 68), ForeColor = Color.White,
FlatStyle = FlatStyle.Flat, Cursor = Cursors.Hand
};
btnDisc.FlatAppearance.BorderSize = 0;
btnDisc.Click += (s, e) => DoDisconnect(opName);
grp.Controls.Add(btnDisc);
// 刷新COM口列表按钮
var btnRefresh = new Button
{
Text = "🔄", Font = normalFont, Size = new Size(36, 30), Location = new Point(415, y1 - 2),
FlatStyle = FlatStyle.Flat, Cursor = Cursors.Hand,
BackColor = Color.FromArgb(229, 231, 235)
};
btnRefresh.FlatAppearance.BorderSize = 0;
btnRefresh.Click += (s, e) => RefreshComPorts(localCmb, opName);
grp.Controls.Add(btnRefresh);
lblStatus = new Label { Text = "● 未连接", Font = boldFont, ForeColor = Color.FromArgb(156, 163, 175),
Location = new Point(470, y1 + 4), AutoSize = true };
grp.Controls.Add(lblStatus);
// Row 2: 最近码值 + 手动发送
var lblBar = new Label { Text = "码值:", Font = normalFont, ForeColor = Color.FromArgb(55, 65, 81),
Location = new Point(20, y2 + 4), AutoSize = true };
grp.Controls.Add(lblBar);
txtBar = new TextBox { Font = normalFont, Location = new Point(90, y2), Size = new Size(300, 28),
BorderStyle = BorderStyle.FixedSingle };
localTxtBar = txtBar; // 更新局部变量
grp.Controls.Add(txtBar);
btnSend = new Button
{
Text = "📤 手动发送", Font = boldFont, Size = new Size(120, 30), Location = new Point(405, y2 - 2),
BackColor = Color.FromArgb(5, 150, 105), ForeColor = Color.White,
FlatStyle = FlatStyle.Flat, Cursor = Cursors.Hand
};
btnSend.FlatAppearance.BorderSize = 0;
btnSend.Click += (s, e) => DoManualSend(opName, localTxtBar);
grp.Controls.Add(btnSend);
// Row 3: 扫码时间
var lblTimeLbl = new Label { Text = "扫码时间:", Font = normalFont, ForeColor = Color.FromArgb(55, 65, 81),
Location = new Point(20, y3 + 4), AutoSize = true };
grp.Controls.Add(lblTimeLbl);
lblTime = new Label { Text = "--", Font = normalFont, ForeColor = Color.FromArgb(31, 41, 55),
Location = new Point(110, y3 + 4), AutoSize = true };
grp.Controls.Add(lblTime);
}
// ── 操作方法 ──
private void DoConnect(string opName, ComboBox cmb)
{
string com = cmb.SelectedItem?.ToString();
if (string.IsNullOrEmpty(com))
{
MessageBox.Show("请选择COM口", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
BarcodeScanner scanner;
if (!BarcodeManager.Scanners.TryGetValue(opName, out scanner))
{
scanner = new BarcodeScanner(opName, MesWorkForm.BarcodeBaudRate);
scanner.BarcodeReceived += (op, code) => BarcodeManager.ManualSend(op, code);
BarcodeManager.Scanners[opName] = scanner;
}
bool ok = scanner.Connect(com);
MessageBox.Show(ok ? $"{opName} 扫码枪已连接 ({com})" : $"{opName} 连接失败请检查COM口",
"连接结果", MessageBoxButtons.OK, ok ? MessageBoxIcon.Information : MessageBoxIcon.Warning);
}
private void DoDisconnect(string opName)
{
if (BarcodeManager.Scanners.TryGetValue(opName, out var scanner))
{
scanner.Disconnect();
MessageBox.Show($"{opName} 扫码枪已断开", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
private void DoManualSend(string opName, TextBox txtBar)
{
string barcode = txtBar.Text.Trim();
if (string.IsNullOrEmpty(barcode))
{
MessageBox.Show("请输入条码值", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
BarcodeManager.ManualSend(opName, barcode);
MessageBox.Show($"已手动发送条码:{barcode}\n工位{opName}", "发送成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void RefreshComPorts(ComboBox cmb, string opName)
{
cmb.Items.Clear();
var ports = BarcodeManager.GetAvailablePorts();
foreach (var p in ports)
cmb.Items.Add(p);
// 自动选中当前配置的COM口或已连接的COM口
if (BarcodeManager.Scanners.TryGetValue(opName, out var scanner) && !string.IsNullOrEmpty(scanner.ComPort))
{
int idx = cmb.Items.IndexOf(scanner.ComPort);
if (idx >= 0) cmb.SelectedIndex = idx;
}
}
// ── 定时刷新状态 ──
private void timer_Refresh_Tick(object sender, EventArgs e)
{
RefreshScannerStatus("OP10", lbl_Status1, txt_Barcode1, lbl_ScanTime1);
RefreshScannerStatus("OP20", lbl_Status2, txt_Barcode2, lbl_ScanTime2);
}
private void RefreshScannerStatus(string opName, Label lblStatus, TextBox txtBar, Label lblTime)
{
if (lblStatus == null) return;
if (BarcodeManager.Scanners.TryGetValue(opName, out var scanner))
{
if (scanner.IsConnected)
{
lblStatus.Text = $"● 已连接 ({scanner.ComPort})";
lblStatus.ForeColor = Color.FromArgb(16, 185, 129); // 绿色
}
else
{
lblStatus.Text = $"● 未连接 ({scanner.ComPort})";
lblStatus.ForeColor = Color.FromArgb(239, 68, 68); // 红色
}
// 仅在有新扫码时更新(避免覆盖用户手动输入)
if (!string.IsNullOrEmpty(scanner.LastBarcode) && txtBar.Text != scanner.LastBarcode && !txtBar.Focused)
txtBar.Text = scanner.LastBarcode;
lblTime.Text = scanner.LastScanTime.HasValue
? scanner.LastScanTime.Value.ToString("yyyy-MM-dd HH:mm:ss")
: "--";
}
else
{
lblStatus.Text = "● 未配置";
lblStatus.ForeColor = Color.FromArgb(156, 163, 175);
lblTime.Text = "--";
}
}
}
}

253
SCADA/Pages/UC_ToolMgmt.Designer.cs generated Normal file
View File

@@ -0,0 +1,253 @@
namespace MesWork.Pages
{
partial class UC_ToolMgmt
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
components.Dispose();
base.Dispose(disposing);
}
#region
private void InitializeComponent()
{
this.pnl_Toolbar = new System.Windows.Forms.Panel();
this.txt_Search = new System.Windows.Forms.TextBox();
this.btn_Search = new System.Windows.Forms.Button();
this.btn_Add = new System.Windows.Forms.Button();
this.btn_Edit = new System.Windows.Forms.Button();
this.btn_Delete = new System.Windows.Forms.Button();
this.btn_Refresh = new System.Windows.Forms.Button();
this.btn_Export = new System.Windows.Forms.Button();
this.dgv_Data = new System.Windows.Forms.DataGridView();
this.pnl_StatusBar = new System.Windows.Forms.Panel();
this.lbl_RecordCount = new System.Windows.Forms.Label();
this.pnl_Toolbar.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dgv_Data)).BeginInit();
this.pnl_StatusBar.SuspendLayout();
this.SuspendLayout();
//
// pnl_Toolbar — 顶部工具栏
//
this.pnl_Toolbar.BackColor = System.Drawing.Color.White;
this.pnl_Toolbar.Controls.Add(this.btn_Export);
this.pnl_Toolbar.Controls.Add(this.btn_Refresh);
this.pnl_Toolbar.Controls.Add(this.btn_Delete);
this.pnl_Toolbar.Controls.Add(this.btn_Edit);
this.pnl_Toolbar.Controls.Add(this.btn_Add);
this.pnl_Toolbar.Controls.Add(this.btn_Search);
this.pnl_Toolbar.Controls.Add(this.txt_Search);
this.pnl_Toolbar.Dock = System.Windows.Forms.DockStyle.Top;
this.pnl_Toolbar.Location = new System.Drawing.Point(0, 0);
this.pnl_Toolbar.Name = "pnl_Toolbar";
this.pnl_Toolbar.Padding = new System.Windows.Forms.Padding(16, 12, 16, 12);
this.pnl_Toolbar.Size = new System.Drawing.Size(1820, 56);
this.pnl_Toolbar.TabIndex = 0;
//
// txt_Search — 搜索框
//
this.txt_Search.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txt_Search.Font = new System.Drawing.Font("微软雅黑", 11F);
this.txt_Search.ForeColor = System.Drawing.Color.FromArgb(156, 163, 175);
this.txt_Search.Location = new System.Drawing.Point(16, 13);
this.txt_Search.Name = "txt_Search";
this.txt_Search.Size = new System.Drawing.Size(280, 27);
this.txt_Search.TabIndex = 0;
this.txt_Search.Text = "输入工具名称搜索...";
this.txt_Search.GotFocus += new System.EventHandler(this.txt_Search_GotFocus);
this.txt_Search.LostFocus += new System.EventHandler(this.txt_Search_LostFocus);
this.txt_Search.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txt_Search_KeyDown);
//
// btn_Search
//
this.btn_Search.BackColor = System.Drawing.Color.FromArgb(74, 144, 217);
this.btn_Search.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Search.FlatAppearance.BorderSize = 0;
this.btn_Search.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Search.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Search.ForeColor = System.Drawing.Color.White;
this.btn_Search.Location = new System.Drawing.Point(306, 12);
this.btn_Search.Name = "btn_Search";
this.btn_Search.Size = new System.Drawing.Size(80, 30);
this.btn_Search.TabIndex = 1;
this.btn_Search.Text = "🔍 搜索";
this.btn_Search.UseVisualStyleBackColor = false;
this.btn_Search.Click += new System.EventHandler(this.btn_Search_Click);
//
// btn_Add
//
this.btn_Add.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
this.btn_Add.BackColor = System.Drawing.Color.FromArgb(74, 144, 217);
this.btn_Add.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Add.FlatAppearance.BorderSize = 0;
this.btn_Add.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Add.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Add.ForeColor = System.Drawing.Color.White;
this.btn_Add.Location = new System.Drawing.Point(1334, 12);
this.btn_Add.Name = "btn_Add";
this.btn_Add.Size = new System.Drawing.Size(88, 30);
this.btn_Add.TabIndex = 2;
this.btn_Add.Text = " 新增";
this.btn_Add.UseVisualStyleBackColor = false;
this.btn_Add.Click += new System.EventHandler(this.btn_Add_Click);
//
// btn_Edit
//
this.btn_Edit.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
this.btn_Edit.BackColor = System.Drawing.Color.FromArgb(245, 158, 11);
this.btn_Edit.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Edit.FlatAppearance.BorderSize = 0;
this.btn_Edit.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Edit.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Edit.ForeColor = System.Drawing.Color.White;
this.btn_Edit.Location = new System.Drawing.Point(1430, 12);
this.btn_Edit.Name = "btn_Edit";
this.btn_Edit.Size = new System.Drawing.Size(88, 30);
this.btn_Edit.TabIndex = 3;
this.btn_Edit.Text = "✏ 修改";
this.btn_Edit.UseVisualStyleBackColor = false;
this.btn_Edit.Click += new System.EventHandler(this.btn_Edit_Click);
//
// btn_Delete
//
this.btn_Delete.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
this.btn_Delete.BackColor = System.Drawing.Color.FromArgb(239, 68, 68);
this.btn_Delete.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Delete.FlatAppearance.BorderSize = 0;
this.btn_Delete.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Delete.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Delete.ForeColor = System.Drawing.Color.White;
this.btn_Delete.Location = new System.Drawing.Point(1526, 12);
this.btn_Delete.Name = "btn_Delete";
this.btn_Delete.Size = new System.Drawing.Size(88, 30);
this.btn_Delete.TabIndex = 4;
this.btn_Delete.Text = "✕ 删除";
this.btn_Delete.UseVisualStyleBackColor = false;
this.btn_Delete.Click += new System.EventHandler(this.btn_Delete_Click);
//
// btn_Refresh
//
this.btn_Refresh.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
this.btn_Refresh.BackColor = System.Drawing.Color.FromArgb(107, 114, 128);
this.btn_Refresh.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Refresh.FlatAppearance.BorderSize = 0;
this.btn_Refresh.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Refresh.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Refresh.ForeColor = System.Drawing.Color.White;
this.btn_Refresh.Location = new System.Drawing.Point(1718, 12);
this.btn_Refresh.Name = "btn_Refresh";
this.btn_Refresh.Size = new System.Drawing.Size(88, 30);
this.btn_Refresh.TabIndex = 5;
this.btn_Refresh.Text = "↻ 刷新";
this.btn_Refresh.UseVisualStyleBackColor = false;
this.btn_Refresh.Click += new System.EventHandler(this.btn_Refresh_Click);
//
// btn_Export
//
this.btn_Export.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
this.btn_Export.BackColor = System.Drawing.Color.FromArgb(5, 150, 105);
this.btn_Export.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Export.FlatAppearance.BorderSize = 0;
this.btn_Export.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Export.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Export.ForeColor = System.Drawing.Color.White;
this.btn_Export.Location = new System.Drawing.Point(1622, 12);
this.btn_Export.Name = "btn_Export";
this.btn_Export.Size = new System.Drawing.Size(88, 30);
this.btn_Export.TabIndex = 6;
this.btn_Export.Text = "📥 导出";
this.btn_Export.UseVisualStyleBackColor = false;
this.btn_Export.Click += new System.EventHandler(this.btn_Export_Click);
//
// dgv_Data — 数据表格
//
this.dgv_Data.AllowUserToAddRows = false;
this.dgv_Data.AllowUserToDeleteRows = false;
this.dgv_Data.AllowUserToResizeRows = false;
this.dgv_Data.BackgroundColor = System.Drawing.Color.White;
this.dgv_Data.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.dgv_Data.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.SingleHorizontal;
this.dgv_Data.ColumnHeadersHeight = 42;
this.dgv_Data.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
this.dgv_Data.ColumnHeadersDefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(232, 237, 242);
this.dgv_Data.ColumnHeadersDefaultCellStyle.ForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
this.dgv_Data.ColumnHeadersDefaultCellStyle.Font = new System.Drawing.Font("微软雅黑", 11F, System.Drawing.FontStyle.Bold);
this.dgv_Data.ColumnHeadersDefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
this.dgv_Data.DefaultCellStyle.ForeColor = System.Drawing.Color.FromArgb(31, 41, 55);
this.dgv_Data.DefaultCellStyle.Font = new System.Drawing.Font("微软雅黑", 11F);
this.dgv_Data.DefaultCellStyle.SelectionBackColor = System.Drawing.Color.FromArgb(219, 234, 254);
this.dgv_Data.DefaultCellStyle.SelectionForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
this.dgv_Data.DefaultCellStyle.Padding = new System.Windows.Forms.Padding(8, 0, 8, 0);
this.dgv_Data.AlternatingRowsDefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(248, 250, 252);
this.dgv_Data.Dock = System.Windows.Forms.DockStyle.Fill;
this.dgv_Data.EnableHeadersVisualStyles = false;
this.dgv_Data.GridColor = System.Drawing.Color.FromArgb(229, 231, 235);
this.dgv_Data.MultiSelect = false;
this.dgv_Data.Name = "dgv_Data";
this.dgv_Data.ReadOnly = true;
this.dgv_Data.RowHeadersVisible = false;
this.dgv_Data.RowTemplate.Height = 38;
this.dgv_Data.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.dgv_Data.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
this.dgv_Data.TabIndex = 1;
this.dgv_Data.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dgv_Data_CellDoubleClick);
//
// pnl_StatusBar — 底部状态栏
//
this.pnl_StatusBar.BackColor = System.Drawing.Color.White;
this.pnl_StatusBar.Controls.Add(this.lbl_RecordCount);
this.pnl_StatusBar.Dock = System.Windows.Forms.DockStyle.Bottom;
this.pnl_StatusBar.Location = new System.Drawing.Point(0, 964);
this.pnl_StatusBar.Name = "pnl_StatusBar";
this.pnl_StatusBar.Padding = new System.Windows.Forms.Padding(16, 6, 16, 6);
this.pnl_StatusBar.Size = new System.Drawing.Size(1820, 36);
this.pnl_StatusBar.TabIndex = 2;
//
// lbl_RecordCount
//
this.lbl_RecordCount.AutoSize = true;
this.lbl_RecordCount.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lbl_RecordCount.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_RecordCount.Location = new System.Drawing.Point(16, 8);
this.lbl_RecordCount.Name = "lbl_RecordCount";
this.lbl_RecordCount.Size = new System.Drawing.Size(82, 20);
this.lbl_RecordCount.TabIndex = 0;
this.lbl_RecordCount.Text = "共 0 条记录";
//
// UC_ToolMgmt
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.Color.FromArgb(245, 247, 250);
this.Controls.Add(this.dgv_Data);
this.Controls.Add(this.pnl_StatusBar);
this.Controls.Add(this.pnl_Toolbar);
this.Name = "UC_ToolMgmt";
this.Size = new System.Drawing.Size(1820, 1000);
this.pnl_Toolbar.ResumeLayout(false);
this.pnl_Toolbar.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dgv_Data)).EndInit();
this.pnl_StatusBar.ResumeLayout(false);
this.pnl_StatusBar.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel pnl_Toolbar;
private System.Windows.Forms.TextBox txt_Search;
private System.Windows.Forms.Button btn_Search;
private System.Windows.Forms.Button btn_Add;
private System.Windows.Forms.Button btn_Edit;
private System.Windows.Forms.Button btn_Delete;
private System.Windows.Forms.Button btn_Refresh;
private System.Windows.Forms.Button btn_Export;
private System.Windows.Forms.DataGridView dgv_Data;
private System.Windows.Forms.Panel pnl_StatusBar;
private System.Windows.Forms.Label lbl_RecordCount;
}
}

159
SCADA/Pages/UC_ToolMgmt.cs Normal file
View File

@@ -0,0 +1,159 @@
using System;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Windows.Forms;
namespace MesWork.Pages
{
/// <summary>
/// 工具管理页面 — 传感器/工具校准和使用管理
/// 对应存储过程工具管理_分页查询、工具管理_新增、工具管理_修改、工具管理_删除
/// </summary>
public partial class UC_ToolMgmt : UserControl
{
private const string SEARCH_HINT = "输入工具名称搜索...";
private PagerBar _pager;
public UC_ToolMgmt()
{
InitializeComponent();
InitColumns();
_pager = new PagerBar();
_pager.PageChanged += (s, e) => LoadData(txt_Search.Text == SEARCH_HINT ? "" : txt_Search.Text.Trim());
this.Controls.Remove(pnl_StatusBar);
this.Controls.Add(_pager);
this.Controls.SetChildIndex(_pager, this.Controls.Count - 2);
}
/// <summary>
/// 预设表格列(确保无数据时也能看到表头结构)
/// </summary>
private void InitColumns()
{
dgv_Data.AutoGenerateColumns = false;
dgv_Data.Columns.Clear();
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "ID", HeaderText = "ID", DataPropertyName = "ID", Visible = false });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "工具名称", HeaderText = "工具名称", DataPropertyName = "工具名称", FillWeight = 110 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "说明", HeaderText = "说明", DataPropertyName = "说明", FillWeight = 120 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "校准值", HeaderText = "校准值", DataPropertyName = "校准值", FillWeight = 70 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "校准时间", HeaderText = "校准时间", DataPropertyName = "校准时间", FillWeight = 90 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "使用次数", HeaderText = "使用次数", DataPropertyName = "使用次数", FillWeight = 60 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "使用次数变更时间", HeaderText = "次数变更时间", DataPropertyName = "使用次数变更时间", FillWeight = 90 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "创建时间", HeaderText = "创建时间", DataPropertyName = "创建时间", FillWeight = 90 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "修改时间", HeaderText = "修改时间", DataPropertyName = "修改时间", FillWeight = 90 });
}
public void LoadData(string keyword = "")
{
try
{
var (pageCountParam, itemCountParam) = PagerBar.CreateOutputParams();
var parms = new SqlParameter[]
{
new SqlParameter("@工具名称", keyword ?? ""),
new SqlParameter("@PageCurrent", _pager.CurrentPage),
new SqlParameter("@PageSize", _pager.PageSize),
pageCountParam,
itemCountParam
};
SqlOperation.ExecuteStoredProcedure("工具管理_分页查询", parms, out DataTable dt, out string err);
if (dt != null) dgv_Data.DataSource = dt;
_pager.UpdateState(pageCountParam, itemCountParam);
}
catch (Exception ex)
{
MessageBox.Show($"查询失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
// ── 搜索框交互 ──
private void txt_Search_GotFocus(object sender, EventArgs e) { CrudHelper.SearchBox_GotFocus(txt_Search, SEARCH_HINT); }
private void txt_Search_LostFocus(object sender, EventArgs e) { CrudHelper.SearchBox_LostFocus(txt_Search, SEARCH_HINT); }
private void txt_Search_KeyDown(object sender, KeyEventArgs e) { if (CrudHelper.SearchBox_KeyDown(e)) btn_Search_Click(sender, e); }
// ── 按钮事件 ──
private void btn_Search_Click(object sender, EventArgs e) { _pager.ResetPage(); LoadData(txt_Search.Text == SEARCH_HINT ? "" : txt_Search.Text.Trim()); }
private void btn_Add_Click(object sender, EventArgs e) => ShowEditDialog(null);
private void btn_Edit_Click(object sender, EventArgs e)
{
if (dgv_Data.CurrentRow != null) ShowEditDialog(dgv_Data.CurrentRow);
else MessageBox.Show("请先选择一条记录", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void btn_Delete_Click(object sender, EventArgs e)
{
if (dgv_Data.CurrentRow == null) { MessageBox.Show("请先选择一条记录", "提示"); return; }
string name = dgv_Data.CurrentRow.Cells["工具名称"]?.Value?.ToString() ?? "";
if (MessageBox.Show($"确认删除工具「{name}」?", "确认删除", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
{
try
{
var parms = new SqlParameter[] { new SqlParameter("@ID", int.Parse(dgv_Data.CurrentRow.Cells["ID"]?.Value?.ToString() ?? "0")) };
SqlOperation.ExecuteStoredProcedure("工具管理_删除", parms, out string err);
LoadData();
}
catch (Exception ex) { MessageBox.Show($"删除失败:{ex.Message}"); }
}
}
private void btn_Refresh_Click(object sender, EventArgs e) { _pager.ResetPage(); LoadData(""); }
private void dgv_Data_CellDoubleClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex >= 0) btn_Edit_Click(sender, e); }
/// <summary>
/// 新增/修改弹窗
/// </summary>
private void ShowEditDialog(DataGridViewRow row)
{
bool isEdit = row != null;
using (var dlg = CrudHelper.CreateEditDialog(isEdit ? "修改工具" : "新增工具", 420, 380))
{
int y = 20;
var txtName = CrudHelper.AddTextField(dlg, "工具名称:", ref y, isEdit ? row.Cells["工具名称"]?.Value?.ToString() : "");
var txtDesc = CrudHelper.AddTextField(dlg, "说明:", ref y, isEdit ? row.Cells["说明"]?.Value?.ToString() : "");
var txtCalVal = CrudHelper.AddTextField(dlg, "校准值:", ref y, isEdit ? row.Cells["校准值"]?.Value?.ToString() : "0");
var txtCalTime = CrudHelper.AddTextField(dlg, "校准时间:", ref y, isEdit ? row.Cells["校准时间"]?.Value?.ToString() : DateTime.Now.ToString("yyyy-MM-dd"));
var txtUseCnt = CrudHelper.AddTextField(dlg, "使用次数:", ref y, isEdit ? row.Cells["使用次数"]?.Value?.ToString() : "0");
CrudHelper.AddDialogButtons(dlg, ref y);
if (dlg.ShowDialog() == DialogResult.OK)
{
try
{
string sp = isEdit ? "工具管理_编辑" : "工具管理_增加";
var pList = new System.Collections.Generic.List<SqlParameter>
{
new SqlParameter("@工具名称", txtName.Text.Trim()),
new SqlParameter("@说明", txtDesc.Text.Trim()),
new SqlParameter("@校准值", txtCalVal.Text.Trim()),
new SqlParameter("@校准时间", DateTime.Parse(txtCalTime.Text)),
new SqlParameter("@使用次数", int.Parse(txtUseCnt.Text))
};
if (isEdit) pList.Insert(0, new SqlParameter("@ID", int.Parse(row.Cells["ID"]?.Value?.ToString() ?? "0")));
SqlOperation.ExecuteStoredProcedure(sp, pList.ToArray(), out string err);
LoadData();
}
catch (Exception ex) { MessageBox.Show($"保存失败:{ex.Message}"); }
}
}
}
private void btn_Export_Click(object sender, EventArgs e)
{
CrudHelper.ExportToExcel("工具管理", "工具管理", () =>
{
string keyword = CrudHelper.GetSearchKeyword(txt_Search, SEARCH_HINT);
var (pageCountParam, itemCountParam) = PagerBar.CreateOutputParams();
var parms = new SqlParameter[]
{
new SqlParameter("@工具名称", keyword),
new SqlParameter("@PageCurrent", 1),
new SqlParameter("@PageSize", 9999999),
pageCountParam, itemCountParam
};
SqlOperation.ExecuteStoredProcedure("工具管理_分页查询", parms, out DataTable dt, out string err);
return dt;
}, dgv_Data.Rows.Count > 0);
}
protected override void OnVisibleChanged(EventArgs e) { base.OnVisibleChanged(e); if (Visible && dgv_Data.DataSource == null) LoadData(); }
}
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata"><xsd:complexType><xsd:sequence><xsd:element name="value" type="xsd:string" minOccurs="0" /></xsd:sequence><xsd:attribute name="name" use="required" type="xsd:string" /><xsd:attribute name="type" type="xsd:string" /><xsd:attribute name="mimetype" type="xsd:string" /><xsd:attribute ref="xml:space" /></xsd:complexType></xsd:element>
<xsd:element name="assembly"><xsd:complexType><xsd:attribute name="alias" type="xsd:string" /><xsd:attribute name="name" type="xsd:string" /></xsd:complexType></xsd:element>
<xsd:element name="data"><xsd:complexType><xsd:sequence><xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /><xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /></xsd:sequence><xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /><xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /><xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /><xsd:attribute ref="xml:space" /></xsd:complexType></xsd:element>
<xsd:element name="resheader"><xsd:complexType><xsd:sequence><xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /></xsd:sequence><xsd:attribute name="name" type="xsd:string" use="required" /></xsd:complexType></xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype"><value>text/microsoft-resx</value></resheader>
<resheader name="version"><value>2.0</value></resheader>
<resheader name="reader"><value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader>
<resheader name="writer"><value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader>
</root>

233
SCADA/Pages/UC_UserMgmt.Designer.cs generated Normal file
View File

@@ -0,0 +1,233 @@
namespace MesWork.Pages
{
partial class UC_UserMgmt
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
components.Dispose();
base.Dispose(disposing);
}
#region
private void InitializeComponent()
{
this.pnl_Toolbar = new System.Windows.Forms.Panel();
this.txt_Search = new System.Windows.Forms.TextBox();
this.btn_Search = new System.Windows.Forms.Button();
this.btn_Add = new System.Windows.Forms.Button();
this.btn_Edit = new System.Windows.Forms.Button();
this.btn_Delete = new System.Windows.Forms.Button();
this.btn_Refresh = new System.Windows.Forms.Button();
this.dgv_Data = new System.Windows.Forms.DataGridView();
this.pnl_StatusBar = new System.Windows.Forms.Panel();
this.lbl_RecordCount = new System.Windows.Forms.Label();
this.pnl_Toolbar.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dgv_Data)).BeginInit();
this.pnl_StatusBar.SuspendLayout();
this.SuspendLayout();
//
// pnl_Toolbar — 顶部工具栏
//
this.pnl_Toolbar.BackColor = System.Drawing.Color.White;
this.pnl_Toolbar.Controls.Add(this.btn_Refresh);
this.pnl_Toolbar.Controls.Add(this.btn_Delete);
this.pnl_Toolbar.Controls.Add(this.btn_Edit);
this.pnl_Toolbar.Controls.Add(this.btn_Add);
this.pnl_Toolbar.Controls.Add(this.btn_Search);
this.pnl_Toolbar.Controls.Add(this.txt_Search);
this.pnl_Toolbar.Dock = System.Windows.Forms.DockStyle.Top;
this.pnl_Toolbar.Location = new System.Drawing.Point(0, 0);
this.pnl_Toolbar.Name = "pnl_Toolbar";
this.pnl_Toolbar.Padding = new System.Windows.Forms.Padding(16, 12, 16, 12);
this.pnl_Toolbar.Size = new System.Drawing.Size(1820, 56);
this.pnl_Toolbar.TabIndex = 0;
//
// txt_Search — 搜索框
//
this.txt_Search.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txt_Search.Font = new System.Drawing.Font("微软雅黑", 11F);
this.txt_Search.ForeColor = System.Drawing.Color.FromArgb(156, 163, 175);
this.txt_Search.Location = new System.Drawing.Point(16, 13);
this.txt_Search.Name = "txt_Search";
this.txt_Search.Size = new System.Drawing.Size(280, 27);
this.txt_Search.TabIndex = 0;
this.txt_Search.Text = "输入姓名搜索...";
this.txt_Search.GotFocus += new System.EventHandler(this.txt_Search_GotFocus);
this.txt_Search.LostFocus += new System.EventHandler(this.txt_Search_LostFocus);
this.txt_Search.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txt_Search_KeyDown);
//
// btn_Search — 搜索按钮
//
this.btn_Search.BackColor = System.Drawing.Color.FromArgb(74, 144, 217);
this.btn_Search.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Search.FlatAppearance.BorderSize = 0;
this.btn_Search.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Search.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Search.ForeColor = System.Drawing.Color.White;
this.btn_Search.Location = new System.Drawing.Point(306, 12);
this.btn_Search.Name = "btn_Search";
this.btn_Search.Size = new System.Drawing.Size(80, 30);
this.btn_Search.TabIndex = 1;
this.btn_Search.Text = "🔍 搜索";
this.btn_Search.UseVisualStyleBackColor = false;
this.btn_Search.Click += new System.EventHandler(this.btn_Search_Click);
//
// btn_Add — 新增
//
this.btn_Add.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
this.btn_Add.BackColor = System.Drawing.Color.FromArgb(74, 144, 217);
this.btn_Add.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Add.FlatAppearance.BorderSize = 0;
this.btn_Add.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Add.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Add.ForeColor = System.Drawing.Color.White;
this.btn_Add.Location = new System.Drawing.Point(1430, 12);
this.btn_Add.Name = "btn_Add";
this.btn_Add.Size = new System.Drawing.Size(88, 30);
this.btn_Add.TabIndex = 2;
this.btn_Add.Text = " 新增";
this.btn_Add.UseVisualStyleBackColor = false;
this.btn_Add.Click += new System.EventHandler(this.btn_Add_Click);
//
// btn_Edit — 修改
//
this.btn_Edit.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
this.btn_Edit.BackColor = System.Drawing.Color.FromArgb(245, 158, 11);
this.btn_Edit.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Edit.FlatAppearance.BorderSize = 0;
this.btn_Edit.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Edit.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Edit.ForeColor = System.Drawing.Color.White;
this.btn_Edit.Location = new System.Drawing.Point(1526, 12);
this.btn_Edit.Name = "btn_Edit";
this.btn_Edit.Size = new System.Drawing.Size(88, 30);
this.btn_Edit.TabIndex = 3;
this.btn_Edit.Text = "✏ 修改";
this.btn_Edit.UseVisualStyleBackColor = false;
this.btn_Edit.Click += new System.EventHandler(this.btn_Edit_Click);
//
// btn_Delete — 删除
//
this.btn_Delete.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
this.btn_Delete.BackColor = System.Drawing.Color.FromArgb(239, 68, 68);
this.btn_Delete.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Delete.FlatAppearance.BorderSize = 0;
this.btn_Delete.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Delete.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Delete.ForeColor = System.Drawing.Color.White;
this.btn_Delete.Location = new System.Drawing.Point(1622, 12);
this.btn_Delete.Name = "btn_Delete";
this.btn_Delete.Size = new System.Drawing.Size(88, 30);
this.btn_Delete.TabIndex = 4;
this.btn_Delete.Text = "✕ 删除";
this.btn_Delete.UseVisualStyleBackColor = false;
this.btn_Delete.Click += new System.EventHandler(this.btn_Delete_Click);
//
// btn_Refresh — 刷新
//
this.btn_Refresh.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
this.btn_Refresh.BackColor = System.Drawing.Color.FromArgb(107, 114, 128);
this.btn_Refresh.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Refresh.FlatAppearance.BorderSize = 0;
this.btn_Refresh.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Refresh.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Refresh.ForeColor = System.Drawing.Color.White;
this.btn_Refresh.Location = new System.Drawing.Point(1718, 12);
this.btn_Refresh.Name = "btn_Refresh";
this.btn_Refresh.Size = new System.Drawing.Size(88, 30);
this.btn_Refresh.TabIndex = 5;
this.btn_Refresh.Text = "↻ 刷新";
this.btn_Refresh.UseVisualStyleBackColor = false;
this.btn_Refresh.Click += new System.EventHandler(this.btn_Refresh_Click);
//
// dgv_Data — 数据表格
//
this.dgv_Data.AllowUserToAddRows = false;
this.dgv_Data.AllowUserToDeleteRows = false;
this.dgv_Data.AllowUserToResizeRows = false;
this.dgv_Data.BackgroundColor = System.Drawing.Color.White;
this.dgv_Data.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.dgv_Data.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.SingleHorizontal;
this.dgv_Data.ColumnHeadersHeight = 42;
this.dgv_Data.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
this.dgv_Data.ColumnHeadersDefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(232, 237, 242);
this.dgv_Data.ColumnHeadersDefaultCellStyle.ForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
this.dgv_Data.ColumnHeadersDefaultCellStyle.Font = new System.Drawing.Font("微软雅黑", 11F, System.Drawing.FontStyle.Bold);
this.dgv_Data.ColumnHeadersDefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
this.dgv_Data.DefaultCellStyle.ForeColor = System.Drawing.Color.FromArgb(31, 41, 55);
this.dgv_Data.DefaultCellStyle.Font = new System.Drawing.Font("微软雅黑", 11F);
this.dgv_Data.DefaultCellStyle.SelectionBackColor = System.Drawing.Color.FromArgb(219, 234, 254);
this.dgv_Data.DefaultCellStyle.SelectionForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
this.dgv_Data.DefaultCellStyle.Padding = new System.Windows.Forms.Padding(8, 0, 8, 0);
this.dgv_Data.AlternatingRowsDefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(248, 250, 252);
this.dgv_Data.Dock = System.Windows.Forms.DockStyle.Fill;
this.dgv_Data.EnableHeadersVisualStyles = false;
this.dgv_Data.GridColor = System.Drawing.Color.FromArgb(229, 231, 235);
this.dgv_Data.MultiSelect = false;
this.dgv_Data.Name = "dgv_Data";
this.dgv_Data.ReadOnly = true;
this.dgv_Data.RowHeadersVisible = false;
this.dgv_Data.RowTemplate.Height = 38;
this.dgv_Data.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.dgv_Data.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
this.dgv_Data.TabIndex = 1;
this.dgv_Data.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dgv_Data_CellDoubleClick);
//
// pnl_StatusBar — 底部状态栏
//
this.pnl_StatusBar.BackColor = System.Drawing.Color.White;
this.pnl_StatusBar.Controls.Add(this.lbl_RecordCount);
this.pnl_StatusBar.Dock = System.Windows.Forms.DockStyle.Bottom;
this.pnl_StatusBar.Location = new System.Drawing.Point(0, 964);
this.pnl_StatusBar.Name = "pnl_StatusBar";
this.pnl_StatusBar.Padding = new System.Windows.Forms.Padding(16, 6, 16, 6);
this.pnl_StatusBar.Size = new System.Drawing.Size(1820, 36);
this.pnl_StatusBar.TabIndex = 2;
//
// lbl_RecordCount — 记录条数
//
this.lbl_RecordCount.AutoSize = true;
this.lbl_RecordCount.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lbl_RecordCount.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_RecordCount.Location = new System.Drawing.Point(16, 8);
this.lbl_RecordCount.Name = "lbl_RecordCount";
this.lbl_RecordCount.Size = new System.Drawing.Size(82, 20);
this.lbl_RecordCount.TabIndex = 0;
this.lbl_RecordCount.Text = "共 0 条记录";
//
// UC_UserMgmt
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.Color.FromArgb(245, 247, 250);
this.Controls.Add(this.dgv_Data);
this.Controls.Add(this.pnl_StatusBar);
this.Controls.Add(this.pnl_Toolbar);
this.Name = "UC_UserMgmt";
this.Size = new System.Drawing.Size(1820, 1000);
this.pnl_Toolbar.ResumeLayout(false);
this.pnl_Toolbar.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dgv_Data)).EndInit();
this.pnl_StatusBar.ResumeLayout(false);
this.pnl_StatusBar.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel pnl_Toolbar;
private System.Windows.Forms.TextBox txt_Search;
private System.Windows.Forms.Button btn_Search;
private System.Windows.Forms.Button btn_Add;
private System.Windows.Forms.Button btn_Edit;
private System.Windows.Forms.Button btn_Delete;
private System.Windows.Forms.Button btn_Refresh;
private System.Windows.Forms.DataGridView dgv_Data;
private System.Windows.Forms.Panel pnl_StatusBar;
private System.Windows.Forms.Label lbl_RecordCount;
}
}

167
SCADA/Pages/UC_UserMgmt.cs Normal file
View File

@@ -0,0 +1,167 @@
using System;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Windows.Forms;
namespace MesWork.Pages
{
/// <summary>
/// 用户管理页面 — CRUD 操作
/// 对应存储过程用户管理_查询、用户管理_增加、用户管理_编辑、用户管理_删除
/// </summary>
public partial class UC_UserMgmt : UserControl
{
private const string SEARCH_HINT = "输入姓名搜索...";
private PagerBar _pager;
public UC_UserMgmt()
{
InitializeComponent();
InitColumns();
// 用PagerBar替换原始pnl_StatusBar
_pager = new PagerBar();
_pager.PageChanged += (s, e) => LoadData(txt_Search.Text == SEARCH_HINT ? "" : txt_Search.Text.Trim());
this.Controls.Remove(pnl_StatusBar);
this.Controls.Add(_pager);
this.Controls.SetChildIndex(_pager, this.Controls.Count - 2);
}
/// <summary>
/// 预设表格列(工号/密码/姓名/性别/权限/创建时间/修改时间)
/// </summary>
private void InitColumns()
{
dgv_Data.AutoGenerateColumns = false;
dgv_Data.Columns.Clear();
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "ID", HeaderText = "ID", DataPropertyName = "ID", Visible = false });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "用户名", HeaderText = "工号", DataPropertyName = "用户名", FillWeight = 100 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "姓名", HeaderText = "姓名", DataPropertyName = "姓名", FillWeight = 100 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "性别", HeaderText = "性别", DataPropertyName = "性别", FillWeight = 50 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "权限", HeaderText = "权限", DataPropertyName = "权限", FillWeight = 60 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "创建时间", HeaderText = "创建时间", DataPropertyName = "创建时间", FillWeight = 100 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "修改时间", HeaderText = "修改时间", DataPropertyName = "修改时间", FillWeight = 100 });
}
// ====================================================================
// 数据加载 — SP: 用户管理_查询(@姓名)
// ====================================================================
public void LoadData(string keyword = "")
{
try
{
var (pageCountParam, itemCountParam) = PagerBar.CreateOutputParams();
var parms = new SqlParameter[]
{
new SqlParameter("@姓名", keyword ?? ""),
new SqlParameter("@PageCurrent", _pager.CurrentPage),
new SqlParameter("@PageSize", _pager.PageSize),
pageCountParam,
itemCountParam
};
SqlOperation.ExecuteStoredProcedure("用户管理_分页查询", parms, out DataTable dt, out string err);
if (dt != null) dgv_Data.DataSource = dt;
_pager.UpdateState(pageCountParam, itemCountParam);
}
catch (Exception ex)
{
MessageBox.Show($"查询失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
// ====================================================================
// 搜索框交互
// ====================================================================
private void txt_Search_GotFocus(object sender, EventArgs e)
{
CrudHelper.SearchBox_GotFocus(txt_Search, SEARCH_HINT);
}
private void txt_Search_LostFocus(object sender, EventArgs e)
{
CrudHelper.SearchBox_LostFocus(txt_Search, SEARCH_HINT);
}
private void txt_Search_KeyDown(object sender, KeyEventArgs e)
{
if (CrudHelper.SearchBox_KeyDown(e)) btn_Search_Click(sender, e);
}
// ====================================================================
// 按钮事件
// ====================================================================
private void btn_Search_Click(object sender, EventArgs e) { _pager.ResetPage(); LoadData(txt_Search.Text == SEARCH_HINT ? "" : txt_Search.Text.Trim()); }
private void btn_Add_Click(object sender, EventArgs e) => ShowEditDialog(null);
private void btn_Edit_Click(object sender, EventArgs e)
{
if (dgv_Data.CurrentRow == null) { MessageBox.Show("请先选择一条记录", "提示"); return; }
ShowEditDialog(dgv_Data.CurrentRow);
}
/// <summary>
/// 删除 — SP: 用户管理_删除(@ID)
/// </summary>
private void btn_Delete_Click(object sender, EventArgs e)
{
if (dgv_Data.CurrentRow == null) { MessageBox.Show("请先选择一条记录", "提示"); return; }
string name = dgv_Data.CurrentRow.Cells["姓名"]?.Value?.ToString() ?? "";
if (MessageBox.Show($"确认删除用户「{name}」?", "确认删除", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
{
try
{
var parms = new SqlParameter[] { new SqlParameter("@ID", int.Parse(dgv_Data.CurrentRow.Cells["ID"]?.Value?.ToString() ?? "0")) };
SqlOperation.ExecuteStoredProcedure("用户管理_删除", parms, out string err);
LoadData();
}
catch (Exception ex) { MessageBox.Show($"删除失败:{ex.Message}"); }
}
}
private void btn_Refresh_Click(object sender, EventArgs e) { _pager.ResetPage(); LoadData(""); }
private void dgv_Data_CellDoubleClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex >= 0) btn_Edit_Click(sender, e); }
// ====================================================================
// 编辑弹窗 — SP: 用户管理_增加 / 用户管理_编辑
// ====================================================================
private void ShowEditDialog(DataGridViewRow row)
{
bool isEdit = row != null;
using (var dlg = CrudHelper.CreateEditDialog(isEdit ? "修改用户" : "新增用户", 420, 380))
{
int y = 20;
var txtJobNo = CrudHelper.AddTextField(dlg, "工号:", ref y, isEdit ? row.Cells["用户名"]?.Value?.ToString() : "", inputX: 110, inputWidth: 260);
var txtPwd = CrudHelper.AddTextField(dlg, "密码:", ref y, "", inputX: 110, inputWidth: 260, isPassword: true);
var txtName = CrudHelper.AddTextField(dlg, "姓名:", ref y, isEdit ? row.Cells["姓名"]?.Value?.ToString() : "", inputX: 110, inputWidth: 260);
var cmbGender = CrudHelper.AddComboField(dlg, "性别:", ref y, new[] { "男", "女" }, isEdit ? row.Cells["性别"]?.Value?.ToString() : "男", inputX: 110, inputWidth: 260);
var cmbPerm = CrudHelper.AddComboField(dlg, "权限:", ref y, new[] { "管理", "操作", "查看" }, isEdit ? row.Cells["权限"]?.Value?.ToString() : "操作", inputX: 110, inputWidth: 260);
CrudHelper.AddDialogButtons(dlg, ref y);
if (dlg.ShowDialog(this) == DialogResult.OK)
{
try
{
string sp = isEdit ? "用户管理_编辑" : "用户管理_增加";
var pList = new System.Collections.Generic.List<SqlParameter>
{
new SqlParameter("@用户名", txtJobNo.Text.Trim()),
new SqlParameter("@密码", txtPwd.Text),
new SqlParameter("@姓名", txtName.Text.Trim()),
new SqlParameter("@性别", cmbGender.Text),
new SqlParameter("@权限", cmbPerm.Text)
};
if (isEdit) pList.Insert(0, new SqlParameter("@ID", int.Parse(row.Cells["ID"]?.Value?.ToString() ?? "0")));
SqlOperation.ExecuteStoredProcedure(sp, pList.ToArray(), out string err);
LoadData();
}
catch (Exception ex) { MessageBox.Show($"保存失败:{ex.Message}"); }
}
}
}
protected override void OnVisibleChanged(EventArgs e) { base.OnVisibleChanged(e); if (Visible && dgv_Data.DataSource == null) LoadData(); }
}
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata"><xsd:complexType><xsd:sequence><xsd:element name="value" type="xsd:string" minOccurs="0" /></xsd:sequence><xsd:attribute name="name" use="required" type="xsd:string" /><xsd:attribute name="type" type="xsd:string" /><xsd:attribute name="mimetype" type="xsd:string" /><xsd:attribute ref="xml:space" /></xsd:complexType></xsd:element>
<xsd:element name="assembly"><xsd:complexType><xsd:attribute name="alias" type="xsd:string" /><xsd:attribute name="name" type="xsd:string" /></xsd:complexType></xsd:element>
<xsd:element name="data"><xsd:complexType><xsd:sequence><xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /><xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /></xsd:sequence><xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /><xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /><xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /><xsd:attribute ref="xml:space" /></xsd:complexType></xsd:element>
<xsd:element name="resheader"><xsd:complexType><xsd:sequence><xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /></xsd:sequence><xsd:attribute name="name" type="xsd:string" use="required" /></xsd:complexType></xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype"><value>text/microsoft-resx</value></resheader>
<resheader name="version"><value>2.0</value></resheader>
<resheader name="reader"><value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader>
<resheader name="writer"><value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader>
</root>

1955
SCADA/Pages/UC_Weighing.Designer.cs generated Normal file

File diff suppressed because it is too large Load Diff

924
SCADA/Pages/UC_Weighing.cs Normal file
View File

@@ -0,0 +1,924 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using DC_A95;
using MesWork;
namespace MesWork.Pages
{
/// <summary>
/// 称重作业页面 — 双工位实时称重监控
/// 信号灯12个(4×3)500ms轮询PLC数据
/// </summary>
public partial class UC_Weighing : UserControl
{
// ── 信号灯名称12个 = 4×3网格──
private static readonly string[] SignalNames =
{
"工件到位", "读取完成", "开始称重", "称重完成",
"请求工作", "允许工作", "请求保存", "保存完成",
"等待放行", "PLC心跳", "PC心跳", "合格标志"
};
/// <summary>信号灯对应的 tagTypeCodeID</summary>
private static readonly int[] SignalTagCodes =
{
2, // 工件到位
100001, // 读取完成
100002, // 开始称重
100003, // 称重完成
44, // 请求工作
66, // 允许工作
19, // 请求保存
20, // 保存完成
100004, // 等待放行
14, // PLC心跳
15, // PC心跳
21 // 合格标志 (Int: 0=无, 1=合格, 2=不合格)
};
private static readonly Color C_SignalOn = Color.FromArgb(16, 185, 129); // 绿色
private static readonly Color C_SignalOff = Color.FromArgb(209, 213, 219); // 灰色
private static readonly Color C_SignalBad = Color.FromArgb(239, 68, 68); // 红色(不合格)
/// <summary>报警代码文本映射</summary>
private static readonly string[] AlarmCodeTexts =
{
"无报警", // 0
"获取工厂数据接口调用失败", // 1
"上传工厂数据接口调用失败", // 2
"发动机号错误" // 3
};
/// <summary>工位1 信号灯面板 [0-11]</summary>
private Panel[] _s1Signals;
/// <summary>工位2 信号灯面板 [0-11]</summary>
private Panel[] _s2Signals;
/// <summary>PLC数据轮询定时器 500ms</summary>
private Timer _tmrPLC;
/// <summary>工位1的opName (如OP10)</summary>
private string _op1;
/// <summary>工位2的opName (如OP20)</summary>
private string _op2;
private bool _isApplyingMetricLayout;
public UC_Weighing()
{
InitializeComponent();
if (IsInDesignMode())
{
ApplyDesignerPreviewLayout();
ApplyWeighingType();
return;
}
Resize += (s, e) => ApplyMetricCardLayout();
pnl_Stations.Resize += (s, e) => ApplyMetricCardLayout();
ApplyMetricCardLayout();
InitSignalLights();
ApplyWeighingType();
InitPLCTimer();
}
private void ApplyMetricCardLayout()
{
if (IsInDesignMode() || _isApplyingMetricLayout || pnl_Stations.ClientSize.Width <= 0)
return;
_isApplyingMetricLayout = true;
try
{
int logHeight = Math.Max(210, Math.Min(280, Height / 4));
if (pnl_Log.Height != logHeight)
pnl_Log.Height = logHeight;
pnl_Stations.Padding = new Padding(12, 12, 12, 10);
int availableWidth = pnl_Stations.ClientSize.Width - pnl_Stations.Padding.Left - pnl_Stations.Padding.Right;
int stationGap = 14;
int stationWidth = Math.Max(620, (availableWidth - stationGap) / 2);
pnl_Station1.Width = stationWidth;
LayoutStationHeaderSection(
pnl_Station1,
pnl_S1_Header,
lbl_S1_Title,
lbl_S1_EngineLabel,
lbl_S1_EngineVal,
lbl_S1_ModelLabel,
lbl_S1_ModelVal,
lbl_S1_OrderLabel,
lbl_S1_OrderVal,
lbl_S1_PalletLabel,
lbl_S1_PalletVal);
LayoutStationHeaderSection(
pnl_Station2,
pnl_S2_Header,
lbl_S2_Title,
lbl_S2_EngineLabel,
lbl_S2_EngineVal,
lbl_S2_ModelLabel,
lbl_S2_ModelVal,
lbl_S2_OrderLabel,
lbl_S2_OrderVal,
lbl_S2_PalletLabel,
lbl_S2_PalletVal);
LayoutStationMetricCards(
pnl_Station1,
pnl_S1_WeightBox,
label1,
lbl_S1_Weight,
lbl_S1_WeightUnit,
pnl_S1_WaterBox,
lbl_S1_WaterTitle,
lbl_S1_Info1,
lbl_S1_WaterUnit,
pnl_S1_MetricBox,
pnl_S1_DensityBox,
lbl_S1_DensityTitle,
lbl_S1_DensityVal,
lbl_S1_DensityUnit,
pnl_S1_AddOilBox,
lbl_S1_AddOilTitle,
lbl_S1_Info2,
lbl_S1_AddOilUnit,
pnl_S1_ExtractOilBox,
lbl_S1_ExtractOilTitle,
lbl_S1_ExtractOilVal,
lbl_S1_ExtractOilUnit,
pnl_S1_OilReleaseBox,
lbl_S1_OilReleaseTitle,
lbl_S1_OilReleaseVal,
lbl_S1_OilReleaseUnit,
pnl_S1_ResidualOilBox,
lbl_S1_ResidualOilTitle,
lbl_S1_ResidualOilVal,
lbl_S1_ResidualOilUnit,
pnl_S1_QualityBox,
lbl_S1_QualityTitle,
lbl_S1_QualityVal);
LayoutStationMetricCards(
pnl_Station2,
pnl_S2_WeightBox,
lbl_S2_WeightTitle,
lbl_S2_Weight,
lbl_S2_WeightUnit,
pnl_S2_WaterBox,
lbl_S2_WaterTitle,
lbl_S2_Info1,
lbl_S2_WaterUnit,
pnl_S2_MetricBox,
pnl_S2_DensityBox,
lbl_S2_DensityTitle,
lbl_S2_DensityVal,
lbl_S2_DensityUnit,
pnl_S2_AddOilBox,
lbl_S2_AddOilTitle,
lbl_S2_Info2,
lbl_S2_AddOilUnit,
pnl_S2_ExtractOilBox,
lbl_S2_ExtractOilTitle,
lbl_S2_ExtractOilVal,
lbl_S2_ExtractOilUnit,
pnl_S2_OilReleaseBox,
lbl_S2_OilReleaseTitle,
lbl_S2_OilReleaseVal,
lbl_S2_OilReleaseUnit,
pnl_S2_ResidualOilBox,
lbl_S2_ResidualOilTitle,
lbl_S2_ResidualOilVal,
lbl_S2_ResidualOilUnit,
pnl_S2_QualityBox,
lbl_S2_QualityTitle,
lbl_S2_QualityVal);
ConfigureAlarmLine(pnl_Station1, lbl_S1_AlarmLabel, lbl_S1_AlarmVal);
ConfigureAlarmLine(pnl_Station2, lbl_S2_AlarmLabel, lbl_S2_AlarmVal);
}
finally
{
_isApplyingMetricLayout = false;
}
}
private void LayoutStationMetricCards(
Panel station,
Panel weightBox,
Label weightTitle,
Label weightValue,
Label weightUnit,
Panel waterBox,
Label waterTitle,
Label waterValue,
Label waterUnit,
Panel metricBox,
Panel densityBox,
Label densityTitle,
Label densityValue,
Label densityUnit,
Panel addOilBox,
Label addOilTitle,
Label addOilValue,
Label addOilUnit,
Panel extractOilBox,
Label extractOilTitle,
Label extractOilValue,
Label extractOilUnit,
Panel oilReleaseBox,
Label oilReleaseTitle,
Label oilReleaseValue,
Label oilReleaseUnit,
Panel residualOilBox,
Label residualOilTitle,
Label residualOilValue,
Label residualOilUnit,
Panel qualityBox,
Label qualityTitle,
Label qualityValue)
{
int margin = 20;
int gap = 16;
int stationWidth = Math.Max(620, station.ClientSize.Width);
int contentWidth = Math.Max(560, stationWidth - margin * 2);
int topCardWidth = Math.Max(250, (contentWidth - gap) / 2);
int metricCardWidth = Math.Max(165, (contentWidth - gap * 2) / 3);
int weightY = 262;
int metricY = 408;
int metricRowGap = 12;
ConfigureWeightCard(weightBox, weightTitle, weightValue, weightUnit, topCardWidth, 128, 41F);
weightBox.Location = new Point(margin, weightY);
ConfigureMetricCard(station, waterBox, waterTitle, waterValue, waterUnit, "水含量", "%", margin + topCardWidth + gap, weightY, topCardWidth, 128, 28F);
metricBox.BackColor = Color.White;
metricBox.Location = new Point(margin, metricY);
metricBox.Size = new Size(contentWidth, 160);
if (metricBox.Parent != station)
station.Controls.Add(metricBox);
ConfigureMetricCard(metricBox, densityBox, densityTitle, densityValue, densityUnit, "油密度", "KG/L", 0, 0, metricCardWidth, 74, 18F);
ConfigureMetricCard(metricBox, addOilBox, addOilTitle, addOilValue, addOilUnit, "加油量", "L", metricCardWidth + gap, 0, metricCardWidth, 74, 18F);
ConfigureMetricCard(metricBox, extractOilBox, extractOilTitle, extractOilValue, extractOilUnit, "抽油量", "L", (metricCardWidth + gap) * 2, 0, metricCardWidth, 74, 18F);
ConfigureMetricCard(metricBox, oilReleaseBox, oilReleaseTitle, oilReleaseValue, oilReleaseUnit, "放油量", "L", 0, 74 + metricRowGap, metricCardWidth, 74, 18F);
ConfigureMetricCard(metricBox, residualOilBox, residualOilTitle, residualOilValue, residualOilUnit, "残油量", "L", metricCardWidth + gap, 74 + metricRowGap, metricCardWidth, 74, 18F);
ConfigureMetricCard(metricBox, qualityBox, qualityTitle, qualityValue, null, "合格结果", "", (metricCardWidth + gap) * 2, 74 + metricRowGap, metricCardWidth, 74, 18F);
}
private void LayoutStationHeaderSection(
Panel station,
Panel headerPanel,
Label titleLabel,
Label engineLabel,
Label engineValue,
Label modelLabel,
Label modelValue,
Label orderLabel,
Label orderValue,
Label palletLabel,
Label palletValue)
{
int margin = 20;
int columnGap = 26;
int labelWidth = 94;
int valueGap = 6;
int headerHeight = 44;
int rowHeight = 38;
int topY = headerHeight + 12;
int contentWidth = Math.Max(560, station.ClientSize.Width - margin * 2);
int columnWidth = (contentWidth - columnGap) / 2;
int valueWidth = Math.Max(120, columnWidth - labelWidth - valueGap);
headerPanel.Height = headerHeight;
titleLabel.Font = new Font("微软雅黑", 12.5F, FontStyle.Bold);
titleLabel.Padding = new Padding(18, 0, 0, 0);
ConfigureInfoPair(engineLabel, engineValue, margin, topY, labelWidth, valueWidth, rowHeight);
ConfigureInfoPair(modelLabel, modelValue, margin + columnWidth + columnGap, topY, labelWidth, valueWidth, rowHeight);
ConfigureInfoPair(orderLabel, orderValue, margin, topY + rowHeight, labelWidth, valueWidth, rowHeight);
ConfigureInfoPair(palletLabel, palletValue, margin + columnWidth + columnGap, topY + rowHeight, labelWidth, valueWidth, rowHeight);
}
private void ConfigureAlarmLine(Panel station, Label alarmLabel, Label alarmValue)
{
int y = 590;
alarmLabel.Font = new Font("微软雅黑", 11.5F, FontStyle.Bold);
alarmLabel.ForeColor = Color.FromArgb(107, 114, 128);
alarmLabel.Location = new Point(20, y);
alarmLabel.Size = new Size(96, 34);
alarmLabel.BringToFront();
alarmValue.Font = new Font("微软雅黑", 11.5F, FontStyle.Bold);
alarmValue.Location = new Point(116, y);
alarmValue.Size = new Size(Math.Max(240, station.ClientSize.Width - 136), 34);
alarmValue.BringToFront();
}
private void ConfigureWeightCard(System.Windows.Forms.Panel panel, System.Windows.Forms.Label titleLabel, System.Windows.Forms.Label valueLabel, System.Windows.Forms.Label unitLabel, int width, int height, float valueFontSize)
{
panel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(250)))), ((int)(((byte)(252)))));
panel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
panel.Size = new System.Drawing.Size(width, height);
titleLabel.AutoSize = false;
titleLabel.Font = new System.Drawing.Font("宋体", 14F, System.Drawing.FontStyle.Bold);
titleLabel.ForeColor = System.Drawing.Color.Black;
titleLabel.Location = new System.Drawing.Point(14, 8);
titleLabel.Size = new System.Drawing.Size(178, 30);
titleLabel.Text = "实时重量";
titleLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
if (titleLabel.Parent != panel)
panel.Controls.Add(titleLabel);
valueLabel.AutoSize = false;
valueLabel.Font = new System.Drawing.Font("Consolas", valueFontSize, System.Drawing.FontStyle.Bold);
valueLabel.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(58)))), ((int)(((byte)(95)))));
valueLabel.Location = new System.Drawing.Point(34, 20);
valueLabel.Size = new System.Drawing.Size(Math.Max(150, width - 122), height - 40);
valueLabel.Text = "0.00";
valueLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
if (valueLabel.Parent != panel)
panel.Controls.Add(valueLabel);
unitLabel.AutoSize = false;
unitLabel.Font = new System.Drawing.Font("微软雅黑", 18F, System.Drawing.FontStyle.Bold);
unitLabel.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(107)))), ((int)(((byte)(114)))), ((int)(((byte)(128)))));
unitLabel.Location = new System.Drawing.Point(width - 82, height - 44);
unitLabel.Size = new System.Drawing.Size(66, 34);
unitLabel.Text = "KG";
unitLabel.TextAlign = System.Drawing.ContentAlignment.BottomRight;
if (unitLabel.Parent != panel)
panel.Controls.Add(unitLabel);
unitLabel.BringToFront();
titleLabel.BringToFront();
}
private void ConfigureMetricCard(System.Windows.Forms.Control parent, System.Windows.Forms.Panel panel, System.Windows.Forms.Label titleLabel, System.Windows.Forms.Label valueLabel, System.Windows.Forms.Label unitLabel, string title, string unit, int x, int y, int width, int height, float valueFontSize)
{
panel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(250)))), ((int)(((byte)(252)))));
panel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
panel.Location = new System.Drawing.Point(x, y);
panel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
panel.Size = new System.Drawing.Size(width, height);
if (panel.Parent != parent)
parent.Controls.Add(panel);
titleLabel.AutoSize = false;
titleLabel.Font = new System.Drawing.Font("宋体", height >= 100 ? 14F : 10.5F, System.Drawing.FontStyle.Bold);
titleLabel.ForeColor = System.Drawing.Color.Black;
titleLabel.Location = new System.Drawing.Point(12, 7);
titleLabel.Size = new System.Drawing.Size(width - 24, height >= 100 ? 30 : 22);
titleLabel.Text = title;
titleLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
if (titleLabel.Parent != panel)
panel.Controls.Add(titleLabel);
valueLabel.AutoSize = false;
valueLabel.BorderStyle = System.Windows.Forms.BorderStyle.None;
valueLabel.BackColor = panel.BackColor;
valueLabel.Font = new System.Drawing.Font("微软雅黑", valueFontSize, System.Drawing.FontStyle.Bold);
valueLabel.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(58)))), ((int)(((byte)(95)))));
int unitWidth = unit == "KG/L" ? 66 : 38;
int valueRightPadding = unitLabel == null ? 16 : unitWidth + 24;
valueLabel.Location = new System.Drawing.Point(20, height >= 100 ? 24 : 20);
valueLabel.Size = new System.Drawing.Size(Math.Max(72, width - 20 - valueRightPadding), height >= 100 ? height - 40 : height - 24);
valueLabel.Text = NormalizeMetricValue(valueLabel.Text);
valueLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
if (valueLabel.Parent != panel)
panel.Controls.Add(valueLabel);
if (unitLabel != null)
{
unitLabel.AutoSize = false;
unitLabel.Font = new System.Drawing.Font("微软雅黑", height >= 100 ? 18F : 11F, System.Drawing.FontStyle.Bold);
unitLabel.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(107)))), ((int)(((byte)(114)))), ((int)(((byte)(128)))));
unitLabel.Location = new System.Drawing.Point(width - unitWidth - 12, height - (height >= 100 ? 42 : 28));
unitLabel.Size = new System.Drawing.Size(unitWidth, height >= 100 ? 30 : 20);
unitLabel.Text = unit;
unitLabel.TextAlign = System.Drawing.ContentAlignment.BottomRight;
if (unitLabel.Parent != panel)
panel.Controls.Add(unitLabel);
unitLabel.BringToFront();
}
titleLabel.BringToFront();
}
private void ConfigureInfoPair(Label titleLabel, Label valueLabel, int x, int y, int titleWidth, int valueWidth, int height)
{
titleLabel.Font = new Font("微软雅黑", 12F, FontStyle.Bold);
titleLabel.ForeColor = Color.FromArgb(107, 114, 128);
titleLabel.Location = new Point(x, y);
titleLabel.Size = new Size(titleWidth, height);
titleLabel.TextAlign = ContentAlignment.MiddleLeft;
valueLabel.Font = new Font("微软雅黑", 13F, FontStyle.Bold);
valueLabel.ForeColor = Color.FromArgb(30, 58, 95);
valueLabel.Location = new Point(x + titleWidth + 6, y);
valueLabel.Size = new Size(valueWidth, height);
valueLabel.TextAlign = ContentAlignment.MiddleLeft;
}
private string NormalizeMetricValue(string text)
{
if (string.IsNullOrWhiteSpace(text))
return "0.00";
int colonIndex = text.IndexOf('');
if (colonIndex >= 0 && colonIndex < text.Length - 1)
text = text.Substring(colonIndex + 1).Trim();
text = text.Trim();
return text == "—" ? "0.00" : text;
}
/// <summary>
/// 根据 App.config 中的 WeighingType 配置切换工位标题
/// </summary>
private void ApplyWeighingType()
{
// 优先从Excel配置读取工位显示名OpName → "OP10 — 称重位1"
var names = MesWorkForm.StationDisplayNames;
var opNames = MesWorkForm.StationOpNames;
string wType = System.Configuration.ConfigurationManager.AppSettings["WeighingType"] ?? "Hanging";
bool isGround = wType.Equals("Ground", StringComparison.OrdinalIgnoreCase);
string dn1 = null, dn2 = null;
string title1 = opNames.Count >= 1 && names.TryGetValue(opNames[0], out dn1)
? dn1
: (isGround ? "工位1 — 地面称重" : "工位1 — 放油前称重");
string title2 = opNames.Count >= 2 && names.TryGetValue(opNames[1], out dn2)
? dn2
: (isGround ? "工位2 — 地面称重" : "工位2 — 放油后称重");
lbl_S1_Title.Text = title1;
lbl_S2_Title.Text = title2;
}
// ====================================================================
// 信号灯创建12个 = 4列×3行
// ====================================================================
private void InitSignalLights()
{
_s1Signals = CreateSignalGrid(pnl_Station1, 20, 136, 198, 36, 22, 12.5F);
_s2Signals = CreateSignalGrid(pnl_Station2, 20, 136, 198, 36, 22, 12.5F);
}
private Panel[] CreateSignalGrid(Panel parent, int startX, int startY)
{
return CreateSignalGrid(parent, startX, startY, 200, 32, 20, 10F);
}
private Panel[] CreateSignalGrid(Panel parent, int startX, int startY, int colSpacing, int rowSpacing, int dotSize, float fontSize)
{
var signals = new Panel[12];
for (int i = 0; i < 12; i++)
{
int col = i % 4;
int row = i / 4;
int x = startX + col * colSpacing;
int y = startY + row * rowSpacing;
var dot = new Panel
{
BackColor = C_SignalOff,
Location = new Point(x, y + 2),
Size = new Size(dotSize, dotSize),
Name = $"sig_{parent.Name}_{i}"
};
dot.Paint += (s, e) =>
{
var p = (Panel)s;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
using (var brush = new SolidBrush(p.BackColor))
{
e.Graphics.Clear(p.Parent.BackColor);
e.Graphics.FillEllipse(brush, 0, 0, p.Width - 1, p.Height - 1);
}
};
var lbl = new Label
{
Text = SignalNames[i],
Font = new Font("微软雅黑", fontSize, FontStyle.Bold),
ForeColor = Color.FromArgb(55, 65, 81),
Location = new Point(x + dotSize + 8, y),
AutoSize = true
};
parent.Controls.Add(dot);
parent.Controls.Add(lbl);
signals[i] = dot;
}
return signals;
}
private bool IsInDesignMode()
{
return LicenseManager.UsageMode == LicenseUsageMode.Designtime || DesignMode || (Site?.DesignMode ?? false);
}
private void ApplyDesignerPreviewLayout()
{
MirrorDesignerStationLayout(
pnl_Station2,
pnl_S2_WeightBox,
lbl_S2_WeightTitle,
lbl_S2_Weight,
lbl_S2_WeightUnit,
lbl_S2_Info1,
pnl_S2_MetricBox,
lbl_S2_DensityVal,
lbl_S2_Info2,
lbl_S2_ExtractOilVal,
lbl_S2_OilReleaseVal,
lbl_S2_ResidualOilVal,
lbl_S2_QualityVal,
lbl_S2_AlarmLabel,
lbl_S2_AlarmVal);
}
private void MirrorDesignerStationLayout(
Panel station,
Panel weightBox,
Label weightTitle,
Label weightValue,
Label weightUnit,
Label waterValue,
Panel metricBox,
Label densityValue,
Label addOilValue,
Label extractOilValue,
Label oilReleaseValue,
Label residualOilValue,
Label qualityValue,
Label alarmLabel,
Label alarmValue)
{
station.Controls.Remove(pnl_S2_WaterBox);
station.Controls.Add(waterValue);
station.Controls.Add(metricBox);
station.Controls.Add(weightBox);
station.Controls.Add(alarmLabel);
station.Controls.Add(alarmValue);
metricBox.Controls.Clear();
metricBox.Controls.Add(qualityValue);
metricBox.Controls.Add(residualOilValue);
metricBox.Controls.Add(oilReleaseValue);
metricBox.Controls.Add(densityValue);
metricBox.Controls.Add(extractOilValue);
metricBox.Controls.Add(addOilValue);
weightBox.Location = new Point(30, 401);
weightBox.Size = new Size(599, 164);
weightTitle.Location = new Point(15, 9);
weightTitle.Size = new Size(137, 30);
weightTitle.Font = new Font("宋体", 15F, FontStyle.Bold);
weightTitle.Text = "实时重量";
weightTitle.AutoSize = true;
weightValue.Location = new Point(114, 9);
weightValue.Size = new Size(327, 144);
weightValue.Font = new Font("Consolas", 54F, FontStyle.Bold);
weightValue.TextAlign = ContentAlignment.MiddleRight;
weightUnit.Location = new Point(456, 60);
weightUnit.Size = new Size(135, 87);
weightUnit.Font = new Font("微软雅黑", 20F, FontStyle.Bold);
weightUnit.TextAlign = ContentAlignment.BottomLeft;
waterValue.BackColor = Color.FromArgb(248, 250, 252);
waterValue.BorderStyle = BorderStyle.FixedSingle;
waterValue.Font = new Font("微软雅黑", 18F, FontStyle.Bold);
waterValue.Location = new Point(660, 401);
waterValue.Size = new Size(599, 164);
waterValue.Text = "水含量0.00";
waterValue.TextAlign = ContentAlignment.MiddleCenter;
waterValue.AutoSize = false;
metricBox.Location = new Point(30, 594);
metricBox.Size = new Size(1230, 174);
metricBox.BackColor = Color.White;
ConfigureDesignerMetricLabel(densityValue, "油密度0.00", 0, 0);
ConfigureDesignerMetricLabel(addOilValue, "加油量0.00", 420, 0);
ConfigureDesignerMetricLabel(extractOilValue, "抽油量0.00", 840, 0);
ConfigureDesignerMetricLabel(oilReleaseValue, "放油量0.00", 0, 93);
ConfigureDesignerMetricLabel(residualOilValue, "残油量0.00", 420, 93);
ConfigureDesignerMetricLabel(qualityValue, "合格结果:--", 840, 93);
alarmLabel.Font = new Font("微软雅黑", 13F, FontStyle.Bold);
alarmLabel.Location = new Point(30, 792);
alarmLabel.Size = new Size(112, 42);
alarmValue.Font = new Font("微软雅黑", 13F, FontStyle.Bold);
alarmValue.Location = new Point(180, 792);
alarmValue.Size = new Size(1080, 42);
alarmValue.Text = "无报警";
}
private void ConfigureDesignerMetricLabel(Label label, string text, int x, int y)
{
label.BackColor = Color.FromArgb(248, 250, 252);
label.BorderStyle = BorderStyle.FixedSingle;
label.Font = new Font("微软雅黑", 13F, FontStyle.Bold);
label.ForeColor = Color.FromArgb(55, 65, 81);
label.Location = new Point(x, y);
label.Size = new Size(389, 80);
label.Text = text;
label.TextAlign = ContentAlignment.MiddleCenter;
label.AutoSize = false;
}
// ====================================================================
// PLC 轮询定时器 — 500ms
// ====================================================================
private void InitPLCTimer()
{
_tmrPLC = new Timer { Interval = 500 };
_tmrPLC.Tick += TmrPLC_Tick;
var tmrDelay = new Timer { Interval = 3000 };
tmrDelay.Tick += (s, e) =>
{
tmrDelay.Stop();
tmrDelay.Dispose();
var ops = MesWorkForm.StationOpNames;
if (ops != null && ops.Count >= 2)
{
_op1 = ops[0];
_op2 = ops[1];
}
else if (ops != null && ops.Count == 1)
{
_op1 = ops[0];
_op2 = ops[0];
}
if (!string.IsNullOrEmpty(_op1))
{
_tmrPLC.Start();
AppendLog($"PLC配置读取工位1={_op1}工位2={_op2 ?? ""}");
}
else
{
AppendLog("未检测到设备工位配置PLC轮询未启动");
}
};
tmrDelay.Start();
}
private void TmrPLC_Tick(object sender, EventArgs e)
{
try
{
if (!string.IsNullOrEmpty(_op1))
PollStation(1, _op1, _s1Signals,
lbl_S1_Weight, lbl_S1_Info1, lbl_S1_Info2,
lbl_S1_PalletVal, lbl_S1_AlarmVal);
if (!string.IsNullOrEmpty(_op2))
PollStation(2, _op2, _s2Signals,
lbl_S2_Weight, lbl_S2_Info1, lbl_S2_Info2,
lbl_S2_PalletVal, lbl_S2_AlarmVal);
}
catch { }
}
/// <summary>
/// 轮询单个工位的所有PLC数据
/// </summary>
private void PollStation(int station, string opName, Panel[] signals,
Label lblWeight, Label lblWater, Label lblOil,
Label lblPallet, Label lblAlarm)
{
try
{
// ── 前11个布尔信号灯 ──
for (int i = 0; i < 11; i++)
{
try
{
var val = PlcLinkForm.ReadPLC(SignalTagCodes[i], opName);
bool active = val != null && val.ToString().ToLower()
.Replace("true", "1").Replace("false", "0") == "1";
var newColor = active ? C_SignalOn : C_SignalOff;
if (signals[i].BackColor != newColor)
{
signals[i].BackColor = newColor;
signals[i].Invalidate();
}
}
catch { }
}
// ── 第12个合格标志(21) — Int类型特殊处理 ──
try
{
var qVal = PlcLinkForm.ReadPLC(21, opName);
int qFlag = qVal != null ? Convert.ToInt32(qVal) : 0;
Color qColor = qFlag == 1 ? C_SignalOn : (qFlag == 2 ? C_SignalBad : C_SignalOff);
if (signals[11].BackColor != qColor)
{
signals[11].BackColor = qColor;
signals[11].Invalidate();
}
var lblQuality = station == 1 ? lbl_S1_QualityVal : lbl_S2_QualityVal;
lblQuality.Text = qFlag == 1 ? "合格" : (qFlag == 2 ? "不合格" : "--");
lblQuality.ForeColor = qFlag == 2 ? C_SignalBad : Color.FromArgb(30, 58, 95);
}
catch { }
// ── 实时重量(100220) ──
try
{
var wv = PlcLinkForm.ReadPLC(100220, opName);
if (wv != null)
{
string newTxt = Convert.ToDouble(wv).ToString("F2");
if (lblWeight.Text != newTxt) lblWeight.Text = newTxt;
}
}
catch { }
// ── 水含量(100180) ──
try
{
var sv = PlcLinkForm.ReadPLC(100180, opName);
if (sv != null)
lblWater.Text = Convert.ToDouble(sv).ToString("F2");
}
catch { }
// ── 托盘号(80) ──
try
{
var pv = PlcLinkForm.ReadPLC(80, opName);
if (pv != null)
{
string pt = PLC_R.GetString_CleanGarbled(pv);
if (!string.IsNullOrEmpty(pt)) lblPallet.Text = pt;
}
}
catch { }
// ── 报警代码(112) — Int → 文本映射 ──
try
{
var av = PlcLinkForm.ReadPLC(112, opName);
int alarmCode = av != null ? Convert.ToInt32(av) : 0;
string alarmText = alarmCode >= 0 && alarmCode < AlarmCodeTexts.Length
? AlarmCodeTexts[alarmCode] : $"未知({alarmCode})";
lblAlarm.Text = alarmText;
lblAlarm.ForeColor = alarmCode > 0
? Color.FromArgb(239, 68, 68) // 红色
: Color.FromArgb(107, 114, 128); // 灰色
}
catch { }
}
catch { }
}
// ====================================================================
// 公共方法 — 供 PLC 通信层 / MIS_Funtion 调用
// ====================================================================
public void UpdateSignal(int station, int index, bool active)
{
var sigs = station == 1 ? _s1Signals : _s2Signals;
if (sigs != null && index >= 0 && index < sigs.Length)
{
sigs[index].BackColor = active ? C_SignalOn : C_SignalOff;
sigs[index].Invalidate();
}
}
public void UpdateWeight(int station, double weight)
{
var lbl = station == 1 ? lbl_S1_Weight : lbl_S2_Weight;
if (lbl.InvokeRequired)
lbl.Invoke(new Action(() => lbl.Text = weight.ToString("F2")));
else
lbl.Text = weight.ToString("F2");
}
public void UpdateStationInfo(int station, string engineNo, string modelNo, string orderNo)
{
Action act = () =>
{
if (station == 1)
{
lbl_S1_EngineVal.Text = engineNo ?? "—";
lbl_S1_ModelVal.Text = modelNo ?? "—";
lbl_S1_OrderVal.Text = orderNo ?? "—";
}
else
{
lbl_S2_EngineVal.Text = engineNo ?? "—";
lbl_S2_ModelVal.Text = modelNo ?? "—";
lbl_S2_OrderVal.Text = orderNo ?? "—";
}
};
if (InvokeRequired) Invoke(act); else act();
}
/// <summary>
/// 更新加油量显示
/// </summary>
public void UpdateOilInfo(int station, decimal addOilQty, decimal extractOilQty)
{
UpdateOilInfo(station, addOilQty, extractOilQty, 0, 0, 0);
}
/// <summary>
/// 更新称重指标显示
/// </summary>
public void UpdateOilInfo(int station, decimal addOilQty, decimal extractOilQty, decimal density, decimal oilReleaseQty, decimal residualOilQty)
{
Action act = () =>
{
if (station == 1)
{
lbl_S1_Info2.Text = addOilQty.ToString("F2");
lbl_S1_ExtractOilVal.Text = extractOilQty.ToString("F2");
lbl_S1_DensityVal.Text = density.ToString("F4");
lbl_S1_OilReleaseVal.Text = oilReleaseQty.ToString("F2");
lbl_S1_ResidualOilVal.Text = residualOilQty.ToString("F2");
}
else
{
lbl_S2_Info2.Text = addOilQty.ToString("F2");
lbl_S2_ExtractOilVal.Text = extractOilQty.ToString("F2");
lbl_S2_DensityVal.Text = density.ToString("F4");
lbl_S2_OilReleaseVal.Text = oilReleaseQty.ToString("F2");
lbl_S2_ResidualOilVal.Text = residualOilQty.ToString("F2");
}
};
if (InvokeRequired) Invoke(act); else act();
}
/// <summary>
/// 更新放油量和残油量显示
/// </summary>
public void UpdateOilResult(int station, decimal oilReleaseQty, decimal residualOilQty)
{
Action act = () =>
{
if (station == 1)
{
lbl_S1_OilReleaseVal.Text = oilReleaseQty.ToString("F2");
lbl_S1_ResidualOilVal.Text = residualOilQty.ToString("F2");
}
else
{
lbl_S2_OilReleaseVal.Text = oilReleaseQty.ToString("F2");
lbl_S2_ResidualOilVal.Text = residualOilQty.ToString("F2");
}
};
if (InvokeRequired) Invoke(act); else act();
}
public void UpdateAuxInfo(int station, string info1, string info2)
{
if (station == 1)
{
lbl_S1_Info1.Text = info1 ?? "";
lbl_S1_Info2.Text = info2 ?? "";
}
else
{
lbl_S2_Info1.Text = info1 ?? "";
lbl_S2_Info2.Text = info2 ?? "";
}
}
/// <summary>
/// 追加操作日志(线程安全)
/// </summary>
public void AppendLog(string msg)
{
if (txt_Log == null) return;
if (txt_Log.InvokeRequired)
{
txt_Log.Invoke(new Action(() => AppendLog(msg)));
return;
}
if (txt_Log.Text.Length > 50000)
txt_Log.Text = txt_Log.Text.Substring(0, 30000);
txt_Log.Text = $"{DateTime.Now:HH:mm:ss} {msg}\r\n{txt_Log.Text}";
}
/// <summary>获取工位序号</summary>
public int GetStationIndex(string opName)
{
if (opName == _op1) return 1;
if (opName == _op2) return 2;
return 1;
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

253
SCADA/Pages/UC_WorkpieceMgmt.Designer.cs generated Normal file
View File

@@ -0,0 +1,253 @@
namespace MesWork.Pages
{
partial class UC_WorkpieceMgmt
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
components.Dispose();
base.Dispose(disposing);
}
#region
private void InitializeComponent()
{
this.pnl_Toolbar = new System.Windows.Forms.Panel();
this.txt_Search = new System.Windows.Forms.TextBox();
this.btn_Search = new System.Windows.Forms.Button();
this.btn_Add = new System.Windows.Forms.Button();
this.btn_Edit = new System.Windows.Forms.Button();
this.btn_Delete = new System.Windows.Forms.Button();
this.btn_Refresh = new System.Windows.Forms.Button();
this.btn_Export = new System.Windows.Forms.Button();
this.dgv_Data = new System.Windows.Forms.DataGridView();
this.pnl_StatusBar = new System.Windows.Forms.Panel();
this.lbl_RecordCount = new System.Windows.Forms.Label();
this.pnl_Toolbar.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dgv_Data)).BeginInit();
this.pnl_StatusBar.SuspendLayout();
this.SuspendLayout();
//
// pnl_Toolbar — 顶部工具栏
//
this.pnl_Toolbar.BackColor = System.Drawing.Color.White;
this.pnl_Toolbar.Controls.Add(this.btn_Export);
this.pnl_Toolbar.Controls.Add(this.btn_Refresh);
this.pnl_Toolbar.Controls.Add(this.btn_Delete);
this.pnl_Toolbar.Controls.Add(this.btn_Edit);
this.pnl_Toolbar.Controls.Add(this.btn_Add);
this.pnl_Toolbar.Controls.Add(this.btn_Search);
this.pnl_Toolbar.Controls.Add(this.txt_Search);
this.pnl_Toolbar.Dock = System.Windows.Forms.DockStyle.Top;
this.pnl_Toolbar.Location = new System.Drawing.Point(0, 0);
this.pnl_Toolbar.Name = "pnl_Toolbar";
this.pnl_Toolbar.Padding = new System.Windows.Forms.Padding(16, 12, 16, 12);
this.pnl_Toolbar.Size = new System.Drawing.Size(1820, 56);
this.pnl_Toolbar.TabIndex = 0;
//
// txt_Search — 搜索框
//
this.txt_Search.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txt_Search.Font = new System.Drawing.Font("微软雅黑", 11F);
this.txt_Search.ForeColor = System.Drawing.Color.FromArgb(156, 163, 175);
this.txt_Search.Location = new System.Drawing.Point(16, 13);
this.txt_Search.Name = "txt_Search";
this.txt_Search.Size = new System.Drawing.Size(280, 27);
this.txt_Search.TabIndex = 0;
this.txt_Search.Text = "输入机型号搜索...";
this.txt_Search.GotFocus += new System.EventHandler(this.txt_Search_GotFocus);
this.txt_Search.LostFocus += new System.EventHandler(this.txt_Search_LostFocus);
this.txt_Search.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txt_Search_KeyDown);
//
// btn_Search
//
this.btn_Search.BackColor = System.Drawing.Color.FromArgb(74, 144, 217);
this.btn_Search.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Search.FlatAppearance.BorderSize = 0;
this.btn_Search.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Search.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Search.ForeColor = System.Drawing.Color.White;
this.btn_Search.Location = new System.Drawing.Point(306, 12);
this.btn_Search.Name = "btn_Search";
this.btn_Search.Size = new System.Drawing.Size(80, 30);
this.btn_Search.TabIndex = 1;
this.btn_Search.Text = "🔍 搜索";
this.btn_Search.UseVisualStyleBackColor = false;
this.btn_Search.Click += new System.EventHandler(this.btn_Search_Click);
//
// btn_Add
//
this.btn_Add.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
this.btn_Add.BackColor = System.Drawing.Color.FromArgb(74, 144, 217);
this.btn_Add.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Add.FlatAppearance.BorderSize = 0;
this.btn_Add.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Add.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Add.ForeColor = System.Drawing.Color.White;
this.btn_Add.Location = new System.Drawing.Point(1334, 12);
this.btn_Add.Name = "btn_Add";
this.btn_Add.Size = new System.Drawing.Size(88, 30);
this.btn_Add.TabIndex = 2;
this.btn_Add.Text = " 新增";
this.btn_Add.UseVisualStyleBackColor = false;
this.btn_Add.Click += new System.EventHandler(this.btn_Add_Click);
//
// btn_Edit
//
this.btn_Edit.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
this.btn_Edit.BackColor = System.Drawing.Color.FromArgb(245, 158, 11);
this.btn_Edit.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Edit.FlatAppearance.BorderSize = 0;
this.btn_Edit.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Edit.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Edit.ForeColor = System.Drawing.Color.White;
this.btn_Edit.Location = new System.Drawing.Point(1430, 12);
this.btn_Edit.Name = "btn_Edit";
this.btn_Edit.Size = new System.Drawing.Size(88, 30);
this.btn_Edit.TabIndex = 3;
this.btn_Edit.Text = "✏ 修改";
this.btn_Edit.UseVisualStyleBackColor = false;
this.btn_Edit.Click += new System.EventHandler(this.btn_Edit_Click);
//
// btn_Delete
//
this.btn_Delete.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
this.btn_Delete.BackColor = System.Drawing.Color.FromArgb(239, 68, 68);
this.btn_Delete.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Delete.FlatAppearance.BorderSize = 0;
this.btn_Delete.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Delete.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Delete.ForeColor = System.Drawing.Color.White;
this.btn_Delete.Location = new System.Drawing.Point(1526, 12);
this.btn_Delete.Name = "btn_Delete";
this.btn_Delete.Size = new System.Drawing.Size(88, 30);
this.btn_Delete.TabIndex = 4;
this.btn_Delete.Text = "✕ 删除";
this.btn_Delete.UseVisualStyleBackColor = false;
this.btn_Delete.Click += new System.EventHandler(this.btn_Delete_Click);
//
// btn_Refresh
//
this.btn_Refresh.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
this.btn_Refresh.BackColor = System.Drawing.Color.FromArgb(107, 114, 128);
this.btn_Refresh.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Refresh.FlatAppearance.BorderSize = 0;
this.btn_Refresh.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Refresh.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Refresh.ForeColor = System.Drawing.Color.White;
this.btn_Refresh.Location = new System.Drawing.Point(1718, 12);
this.btn_Refresh.Name = "btn_Refresh";
this.btn_Refresh.Size = new System.Drawing.Size(88, 30);
this.btn_Refresh.TabIndex = 5;
this.btn_Refresh.Text = "↻ 刷新";
this.btn_Refresh.UseVisualStyleBackColor = false;
this.btn_Refresh.Click += new System.EventHandler(this.btn_Refresh_Click);
//
// btn_Export
//
this.btn_Export.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
this.btn_Export.BackColor = System.Drawing.Color.FromArgb(5, 150, 105);
this.btn_Export.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Export.FlatAppearance.BorderSize = 0;
this.btn_Export.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Export.Font = new System.Drawing.Font("微软雅黑", 10F, System.Drawing.FontStyle.Bold);
this.btn_Export.ForeColor = System.Drawing.Color.White;
this.btn_Export.Location = new System.Drawing.Point(1622, 12);
this.btn_Export.Name = "btn_Export";
this.btn_Export.Size = new System.Drawing.Size(88, 30);
this.btn_Export.TabIndex = 6;
this.btn_Export.Text = "📥 导出";
this.btn_Export.UseVisualStyleBackColor = false;
this.btn_Export.Click += new System.EventHandler(this.btn_Export_Click);
//
// dgv_Data — 数据表格
//
this.dgv_Data.AllowUserToAddRows = false;
this.dgv_Data.AllowUserToDeleteRows = false;
this.dgv_Data.AllowUserToResizeRows = false;
this.dgv_Data.BackgroundColor = System.Drawing.Color.White;
this.dgv_Data.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.dgv_Data.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.SingleHorizontal;
this.dgv_Data.ColumnHeadersHeight = 42;
this.dgv_Data.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
this.dgv_Data.ColumnHeadersDefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(232, 237, 242);
this.dgv_Data.ColumnHeadersDefaultCellStyle.ForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
this.dgv_Data.ColumnHeadersDefaultCellStyle.Font = new System.Drawing.Font("微软雅黑", 11F, System.Drawing.FontStyle.Bold);
this.dgv_Data.ColumnHeadersDefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
this.dgv_Data.DefaultCellStyle.ForeColor = System.Drawing.Color.FromArgb(31, 41, 55);
this.dgv_Data.DefaultCellStyle.Font = new System.Drawing.Font("微软雅黑", 11F);
this.dgv_Data.DefaultCellStyle.SelectionBackColor = System.Drawing.Color.FromArgb(219, 234, 254);
this.dgv_Data.DefaultCellStyle.SelectionForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
this.dgv_Data.DefaultCellStyle.Padding = new System.Windows.Forms.Padding(8, 0, 8, 0);
this.dgv_Data.AlternatingRowsDefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(248, 250, 252);
this.dgv_Data.Dock = System.Windows.Forms.DockStyle.Fill;
this.dgv_Data.EnableHeadersVisualStyles = false;
this.dgv_Data.GridColor = System.Drawing.Color.FromArgb(229, 231, 235);
this.dgv_Data.MultiSelect = false;
this.dgv_Data.Name = "dgv_Data";
this.dgv_Data.ReadOnly = true;
this.dgv_Data.RowHeadersVisible = false;
this.dgv_Data.RowTemplate.Height = 38;
this.dgv_Data.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.dgv_Data.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
this.dgv_Data.TabIndex = 1;
this.dgv_Data.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dgv_Data_CellDoubleClick);
//
// pnl_StatusBar — 底部状态栏
//
this.pnl_StatusBar.BackColor = System.Drawing.Color.White;
this.pnl_StatusBar.Controls.Add(this.lbl_RecordCount);
this.pnl_StatusBar.Dock = System.Windows.Forms.DockStyle.Bottom;
this.pnl_StatusBar.Location = new System.Drawing.Point(0, 964);
this.pnl_StatusBar.Name = "pnl_StatusBar";
this.pnl_StatusBar.Padding = new System.Windows.Forms.Padding(16, 6, 16, 6);
this.pnl_StatusBar.Size = new System.Drawing.Size(1820, 36);
this.pnl_StatusBar.TabIndex = 2;
//
// lbl_RecordCount
//
this.lbl_RecordCount.AutoSize = true;
this.lbl_RecordCount.Font = new System.Drawing.Font("微软雅黑", 10F);
this.lbl_RecordCount.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
this.lbl_RecordCount.Location = new System.Drawing.Point(16, 8);
this.lbl_RecordCount.Name = "lbl_RecordCount";
this.lbl_RecordCount.Size = new System.Drawing.Size(82, 20);
this.lbl_RecordCount.TabIndex = 0;
this.lbl_RecordCount.Text = "共 0 条记录";
//
// UC_WorkpieceMgmt
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.Color.FromArgb(245, 247, 250);
this.Controls.Add(this.dgv_Data);
this.Controls.Add(this.pnl_StatusBar);
this.Controls.Add(this.pnl_Toolbar);
this.Name = "UC_WorkpieceMgmt";
this.Size = new System.Drawing.Size(1820, 1000);
this.pnl_Toolbar.ResumeLayout(false);
this.pnl_Toolbar.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dgv_Data)).EndInit();
this.pnl_StatusBar.ResumeLayout(false);
this.pnl_StatusBar.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel pnl_Toolbar;
private System.Windows.Forms.TextBox txt_Search;
private System.Windows.Forms.Button btn_Search;
private System.Windows.Forms.Button btn_Add;
private System.Windows.Forms.Button btn_Edit;
private System.Windows.Forms.Button btn_Delete;
private System.Windows.Forms.Button btn_Refresh;
private System.Windows.Forms.Button btn_Export;
private System.Windows.Forms.DataGridView dgv_Data;
private System.Windows.Forms.Panel pnl_StatusBar;
private System.Windows.Forms.Label lbl_RecordCount;
}
}

View File

@@ -0,0 +1,654 @@
using System;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Windows.Forms;
namespace MesWork.Pages
{
/// <summary>
/// 工件管理页面 — 各机型参数维护(加油量/抽油量/密度)
/// 对应存储过程工件管理_查询、工件管理_增加、工件管理_编辑、工件管理_删除
/// </summary>
public partial class UC_WorkpieceMgmt : UserControl
{
private const string SEARCH_HINT = "输入机型号搜索...";
private PagerBar _pager;
public UC_WorkpieceMgmt()
{
InitializeComponent();
InitColumns();
_pager = new PagerBar();
_pager.PageChanged += (s, e) => LoadData(txt_Search.Text == SEARCH_HINT ? "" : txt_Search.Text.Trim());
this.Controls.Remove(pnl_StatusBar);
this.Controls.Add(_pager);
this.Controls.SetChildIndex(_pager, this.Controls.Count - 2);
}
/// <summary>
/// 预设表格列(确保无数据时也能看到表头结构)
/// </summary>
private void InitColumns()
{
dgv_Data.AutoGenerateColumns = false;
dgv_Data.Columns.Clear();
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "ID", HeaderText = "ID", DataPropertyName = "ID", Visible = false });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "机型号", HeaderText = "机型号", DataPropertyName = "机型号", FillWeight = 120 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "说明", HeaderText = "说明", DataPropertyName = "说明", FillWeight = 130 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "加油量", HeaderText = "加油量(L)", DataPropertyName = "加油量", FillWeight = 70 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "抽油量", HeaderText = "抽油量(L)", DataPropertyName = "抽油量", FillWeight = 70 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "密度", HeaderText = "密度(kg/L)", DataPropertyName = "密度", FillWeight = 70 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "残油量上限", HeaderText = "残油量上限(L)", DataPropertyName = "残油量上限", FillWeight = 70 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "残油量下限", HeaderText = "残油量下限(L)", DataPropertyName = "残油量下限", FillWeight = 70 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "创建时间", HeaderText = "创建时间", DataPropertyName = "创建时间", FillWeight = 100 });
dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "修改时间", HeaderText = "修改时间", DataPropertyName = "修改时间", FillWeight = 100 });
}
public void LoadData(string keyword = "")
{
try
{
var (pageCountParam, itemCountParam) = PagerBar.CreateOutputParams();
var parms = new SqlParameter[]
{
new SqlParameter("@机型号", keyword ?? ""),
new SqlParameter("@PageCurrent", _pager.CurrentPage),
new SqlParameter("@PageSize", _pager.PageSize),
pageCountParam,
itemCountParam
};
SqlOperation.ExecuteStoredProcedure("工件管理_分页查询", parms, out DataTable dt, out string err);
if (dt != null) dgv_Data.DataSource = dt;
_pager.UpdateState(pageCountParam, itemCountParam);
}
catch (Exception ex)
{
MessageBox.Show($"查询失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
// ── 搜索框交互 ──
private void txt_Search_GotFocus(object sender, EventArgs e) { CrudHelper.SearchBox_GotFocus(txt_Search, SEARCH_HINT); }
private void txt_Search_LostFocus(object sender, EventArgs e) { CrudHelper.SearchBox_LostFocus(txt_Search, SEARCH_HINT); }
private void txt_Search_KeyDown(object sender, KeyEventArgs e) { if (CrudHelper.SearchBox_KeyDown(e)) btn_Search_Click(sender, e); }
// ── 按钮事件 ──
private void btn_Search_Click(object sender, EventArgs e) { _pager.ResetPage(); LoadData(txt_Search.Text == SEARCH_HINT ? "" : txt_Search.Text.Trim()); }
private void btn_Add_Click(object sender, EventArgs e) => ShowEditDialog(null);
private void btn_Edit_Click(object sender, EventArgs e)
{
if (dgv_Data.CurrentRow != null) ShowEditDialog(dgv_Data.CurrentRow);
else MessageBox.Show("请先选择一条记录", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void btn_Delete_Click(object sender, EventArgs e)
{
if (dgv_Data.CurrentRow == null) { MessageBox.Show("请先选择一条记录", "提示"); return; }
string name = dgv_Data.CurrentRow.Cells["机型号"]?.Value?.ToString() ?? "";
if (MessageBox.Show($"确认删除工件「{name}」?", "确认删除", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
{
try
{
var parms = new SqlParameter[] { new SqlParameter("@ID", int.Parse(dgv_Data.CurrentRow.Cells["ID"]?.Value?.ToString() ?? "0")) };
SqlOperation.ExecuteStoredProcedure("工件管理_删除", parms, out string err);
LoadData();
}
catch (Exception ex) { MessageBox.Show($"删除失败:{ex.Message}"); }
}
}
private void btn_Refresh_Click(object sender, EventArgs e) { _pager.ResetPage(); LoadData(""); }
private void dgv_Data_CellDoubleClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex >= 0) btn_Edit_Click(sender, e); }
/// <summary>
/// 新增/修改弹窗
/// </summary>
private void ShowEditDialog(DataGridViewRow row)
{
bool isEdit = row != null;
using (var dlg = CrudHelper.CreateEditDialog(isEdit ? "修改工件" : "新增工件", 500, 450))
{
int y = 20;
var txtModel = CrudHelper.AddTextField(dlg, "机型号:", ref y, isEdit ? row.Cells["机型号"]?.Value?.ToString() : "", inputX: 170, inputWidth: 280);
var txtDesc = CrudHelper.AddTextField(dlg, "说明:", ref y, isEdit ? row.Cells["说明"]?.Value?.ToString() : "", inputX: 170, inputWidth: 280);
var txtOilIn = CrudHelper.AddTextField(dlg, "加油量(L)", ref y, isEdit ? row.Cells["加油量"]?.Value?.ToString() : "0", inputX: 170, inputWidth: 280);
var txtOilOut = CrudHelper.AddTextField(dlg, "抽油量(L)", ref y, isEdit ? row.Cells["抽油量"]?.Value?.ToString() : "0", inputX: 170, inputWidth: 280);
var txtDensity = CrudHelper.AddTextField(dlg, "密度(kg/L)", ref y, isEdit ? row.Cells["密度"]?.Value?.ToString() : "0.85", inputX: 170, inputWidth: 280);
var txtOilMax = CrudHelper.AddTextField(dlg, "残油量上限(L)", ref y, isEdit ? row.Cells["残油量上限"]?.Value?.ToString() : "0", inputX: 170, inputWidth: 280);
var txtOilMin = CrudHelper.AddTextField(dlg, "残油量下限(L)", ref y, isEdit ? row.Cells["残油量下限"]?.Value?.ToString() : "0", inputX: 170, inputWidth: 280);
CrudHelper.AddDialogButtons(dlg, ref y);
if (dlg.ShowDialog() == DialogResult.OK)
{
try
{
string sp = isEdit ? "工件管理_编辑" : "工件管理_增加";
var pList = new System.Collections.Generic.List<SqlParameter>
{
new SqlParameter("@机型号", txtModel.Text.Trim()),
new SqlParameter("@说明", txtDesc.Text.Trim()),
new SqlParameter("@加油量", decimal.Parse(txtOilIn.Text)),
new SqlParameter("@抽油量", decimal.Parse(txtOilOut.Text)),
new SqlParameter("@密度", decimal.Parse(txtDensity.Text)),
new SqlParameter("@残油量上限", decimal.Parse(txtOilMax.Text)),
new SqlParameter("@残油量下限", decimal.Parse(txtOilMin.Text))
};
if (isEdit) pList.Insert(0, new SqlParameter("@ID", int.Parse(row.Cells["ID"]?.Value?.ToString() ?? "0")));
SqlOperation.ExecuteStoredProcedure(sp, pList.ToArray(), out string err);
LoadData();
}
catch (Exception ex) { MessageBox.Show($"保存失败:{ex.Message}"); }
}
}
}
private void btn_Export_Click(object sender, EventArgs e)
{
CrudHelper.ExportToExcel("工件管理", "工件管理", () =>
{
string keyword = CrudHelper.GetSearchKeyword(txt_Search, SEARCH_HINT);
var (pageCountParam, itemCountParam) = PagerBar.CreateOutputParams();
var parms = new SqlParameter[]
{
new SqlParameter("@机型号", keyword),
new SqlParameter("@PageCurrent", 1),
new SqlParameter("@PageSize", 9999999),
pageCountParam, itemCountParam
};
SqlOperation.ExecuteStoredProcedure("工件管理_分页查询", parms, out DataTable dt, out string err);
return dt;
}, dgv_Data.Rows.Count > 0);
}
protected override void OnVisibleChanged(EventArgs e) { base.OnVisibleChanged(e); if (Visible && dgv_Data.DataSource == null) LoadData(); }
}
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata"><xsd:complexType><xsd:sequence><xsd:element name="value" type="xsd:string" minOccurs="0" /></xsd:sequence><xsd:attribute name="name" use="required" type="xsd:string" /><xsd:attribute name="type" type="xsd:string" /><xsd:attribute name="mimetype" type="xsd:string" /><xsd:attribute ref="xml:space" /></xsd:complexType></xsd:element>
<xsd:element name="assembly"><xsd:complexType><xsd:attribute name="alias" type="xsd:string" /><xsd:attribute name="name" type="xsd:string" /></xsd:complexType></xsd:element>
<xsd:element name="data"><xsd:complexType><xsd:sequence><xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /><xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /></xsd:sequence><xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /><xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /><xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /><xsd:attribute ref="xml:space" /></xsd:complexType></xsd:element>
<xsd:element name="resheader"><xsd:complexType><xsd:sequence><xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /></xsd:sequence><xsd:attribute name="name" type="xsd:string" use="required" /></xsd:complexType></xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype"><value>text/microsoft-resx</value></resheader>
<resheader name="version"><value>2.0</value></resheader>
<resheader name="reader"><value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader>
<resheader name="writer"><value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></resheader>
</root>