首次提交
This commit is contained in:
BIN
DLL/BasicData.dll
Normal file
BIN
DLL/BasicData.dll
Normal file
Binary file not shown.
BIN
DLL/BouncyCastle.Crypto.dll
Normal file
BIN
DLL/BouncyCastle.Crypto.dll
Normal file
Binary file not shown.
BIN
DLL/ConLink.dll
Normal file
BIN
DLL/ConLink.dll
Normal file
Binary file not shown.
BIN
DLL/ConLink19.dll
Normal file
BIN
DLL/ConLink19.dll
Normal file
Binary file not shown.
BIN
DLL/DataLinkMesWork.dll
Normal file
BIN
DLL/DataLinkMesWork.dll
Normal file
Binary file not shown.
BIN
DLL/DynamicExpresso.Core.dll
Normal file
BIN
DLL/DynamicExpresso.Core.dll
Normal file
Binary file not shown.
BIN
DLL/EnBaseM.dll
Normal file
BIN
DLL/EnBaseM.dll
Normal file
Binary file not shown.
BIN
DLL/ICSharpCode.SharpZipLib.dll
Normal file
BIN
DLL/ICSharpCode.SharpZipLib.dll
Normal file
Binary file not shown.
BIN
DLL/MQTTnet.Extensions.ManagedClient.dll
Normal file
BIN
DLL/MQTTnet.Extensions.ManagedClient.dll
Normal file
Binary file not shown.
BIN
DLL/MQTTnet.dll
Normal file
BIN
DLL/MQTTnet.dll
Normal file
Binary file not shown.
BIN
DLL/MW_Log.dll
Normal file
BIN
DLL/MW_Log.dll
Normal file
Binary file not shown.
BIN
DLL/MesWork.Control.dll
Normal file
BIN
DLL/MesWork.Control.dll
Normal file
Binary file not shown.
BIN
DLL/MesWork.DeviceDriver.dll
Normal file
BIN
DLL/MesWork.DeviceDriver.dll
Normal file
Binary file not shown.
BIN
DLL/Microsoft.Extensions.DependencyInjection.Abstractions.dll
Normal file
BIN
DLL/Microsoft.Extensions.DependencyInjection.Abstractions.dll
Normal file
Binary file not shown.
BIN
DLL/Microsoft.Extensions.Logging.Abstractions.dll
Normal file
BIN
DLL/Microsoft.Extensions.Logging.Abstractions.dll
Normal file
Binary file not shown.
BIN
DLL/Microsoft.Extensions.Logging.dll
Normal file
BIN
DLL/Microsoft.Extensions.Logging.dll
Normal file
Binary file not shown.
BIN
DLL/Microsoft.Extensions.Options.dll
Normal file
BIN
DLL/Microsoft.Extensions.Options.dll
Normal file
Binary file not shown.
BIN
DLL/Microsoft.Extensions.Primitives.dll
Normal file
BIN
DLL/Microsoft.Extensions.Primitives.dll
Normal file
Binary file not shown.
BIN
DLL/Microsoft.Win32.Primitives.dll
Normal file
BIN
DLL/Microsoft.Win32.Primitives.dll
Normal file
Binary file not shown.
BIN
DLL/MySql.Data.dll
Normal file
BIN
DLL/MySql.Data.dll
Normal file
Binary file not shown.
17803
DLL/MySql.Data.xml
Normal file
17803
DLL/MySql.Data.xml
Normal file
File diff suppressed because it is too large
Load Diff
BIN
DLL/NPOI.OOXML.dll
Normal file
BIN
DLL/NPOI.OOXML.dll
Normal file
Binary file not shown.
BIN
DLL/NPOI.OpenXml4Net.dll
Normal file
BIN
DLL/NPOI.OpenXml4Net.dll
Normal file
Binary file not shown.
BIN
DLL/NPOI.OpenXmlFormats.dll
Normal file
BIN
DLL/NPOI.OpenXmlFormats.dll
Normal file
Binary file not shown.
BIN
DLL/NPOI.dll
Normal file
BIN
DLL/NPOI.dll
Normal file
Binary file not shown.
BIN
DLL/Nai.Communication.Robot.FanucVarProxy.dll
Normal file
BIN
DLL/Nai.Communication.Robot.FanucVarProxy.dll
Normal file
Binary file not shown.
BIN
DLL/Newtonsoft.Json.dll
Normal file
BIN
DLL/Newtonsoft.Json.dll
Normal file
Binary file not shown.
BIN
DLL/Opc.Ua.Client.dll
Normal file
BIN
DLL/Opc.Ua.Client.dll
Normal file
Binary file not shown.
BIN
DLL/Opc.Ua.Configuration.dll
Normal file
BIN
DLL/Opc.Ua.Configuration.dll
Normal file
Binary file not shown.
BIN
DLL/Opc.Ua.Core.dll
Normal file
BIN
DLL/Opc.Ua.Core.dll
Normal file
Binary file not shown.
BIN
DLL/OpcUaHelper.dll
Normal file
BIN
DLL/OpcUaHelper.dll
Normal file
Binary file not shown.
BIN
DLL/Rhino3dm.dll
Normal file
BIN
DLL/Rhino3dm.dll
Normal file
Binary file not shown.
BIN
DLL/Robot.Common.dll
Normal file
BIN
DLL/Robot.Common.dll
Normal file
Binary file not shown.
BIN
DLL/Robot.MessageBus.dll
Normal file
BIN
DLL/Robot.MessageBus.dll
Normal file
Binary file not shown.
BIN
DLL/RobotMapper.dll
Normal file
BIN
DLL/RobotMapper.dll
Normal file
Binary file not shown.
BIN
DLL/RobotStudio.Services.RobApi.Desktop.dll
Normal file
BIN
DLL/RobotStudio.Services.RobApi.Desktop.dll
Normal file
Binary file not shown.
BIN
DLL/RobotStudio.Services.RobApi.dll
Normal file
BIN
DLL/RobotStudio.Services.RobApi.dll
Normal file
Binary file not shown.
BIN
DLL/Robots.dll
Normal file
BIN
DLL/Robots.dll
Normal file
Binary file not shown.
BIN
DLL/S7.Net.dll
Normal file
BIN
DLL/S7.Net.dll
Normal file
Binary file not shown.
BIN
DLL/Serilog.Extensions.Logging.dll
Normal file
BIN
DLL/Serilog.Extensions.Logging.dll
Normal file
Binary file not shown.
BIN
DLL/Serilog.dll
Normal file
BIN
DLL/Serilog.dll
Normal file
Binary file not shown.
BIN
DLL/SqlCmd.dll
Normal file
BIN
DLL/SqlCmd.dll
Normal file
Binary file not shown.
BIN
DLL/System.Buffers.dll
Normal file
BIN
DLL/System.Buffers.dll
Normal file
Binary file not shown.
BIN
DLL/System.Net.Http.Formatting.dll
Normal file
BIN
DLL/System.Net.Http.Formatting.dll
Normal file
Binary file not shown.
BIN
DLL/System.Net.Http.dll
Normal file
BIN
DLL/System.Net.Http.dll
Normal file
Binary file not shown.
BIN
DLL/System.Runtime.CompilerServices.Unsafe.dll
Normal file
BIN
DLL/System.Runtime.CompilerServices.Unsafe.dll
Normal file
Binary file not shown.
BIN
DLL/System.Runtime.InteropServices.RuntimeInformation.dll
Normal file
BIN
DLL/System.Runtime.InteropServices.RuntimeInformation.dll
Normal file
Binary file not shown.
BIN
DLL/System.Web.Cors.dll
Normal file
BIN
DLL/System.Web.Cors.dll
Normal file
Binary file not shown.
BIN
DLL/System.Web.Http.Cors.dll
Normal file
BIN
DLL/System.Web.Http.Cors.dll
Normal file
Binary file not shown.
BIN
DLL/System.Web.Http.SelfHost.dll
Normal file
BIN
DLL/System.Web.Http.SelfHost.dll
Normal file
Binary file not shown.
BIN
DLL/System.Web.Http.dll
Normal file
BIN
DLL/System.Web.Http.dll
Normal file
Binary file not shown.
BIN
DLL/Ubiety.Dns.Core.dll
Normal file
BIN
DLL/Ubiety.Dns.Core.dll
Normal file
Binary file not shown.
BIN
DLL/WeifenLuo.WinFormsUI.Docking.ThemeVS2015.dll
Normal file
BIN
DLL/WeifenLuo.WinFormsUI.Docking.ThemeVS2015.dll
Normal file
Binary file not shown.
BIN
DLL/WeifenLuo.WinFormsUI.Docking.dll
Normal file
BIN
DLL/WeifenLuo.WinFormsUI.Docking.dll
Normal file
Binary file not shown.
BIN
DLL/Zstandard.Net.dll
Normal file
BIN
DLL/Zstandard.Net.dll
Normal file
Binary file not shown.
BIN
DLL/log4net.dll
Normal file
BIN
DLL/log4net.dll
Normal file
Binary file not shown.
BIN
DLL/netstandard.dll
Normal file
BIN
DLL/netstandard.dll
Normal file
Binary file not shown.
57
MW_Log/01_MW_Log.csproj
Normal file
57
MW_Log/01_MW_Log.csproj
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{1AC112C4-2400-4D03-A26D-2E3ACE6FE6D4}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>MW_Log</RootNamespace>
|
||||||
|
<AssemblyName>MW_Log</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<Deterministic>true</Deterministic>
|
||||||
|
<TargetFrameworkProfile />
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="log4net">
|
||||||
|
<HintPath>..\DLL\log4net.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="LoggerHelper.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="log4net.config">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
</Project>
|
||||||
49
MW_Log/LoggerHelper.cs
Normal file
49
MW_Log/LoggerHelper.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
using log4net;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MW_Log
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// LoggerHelper
|
||||||
|
/// </summary>
|
||||||
|
public class LoggerHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// LogInfo
|
||||||
|
/// </summary>
|
||||||
|
private static readonly ILog LogInfo = LogManager.GetLogger("LogInfo");
|
||||||
|
/// <summary>
|
||||||
|
/// 记录Info日志
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="msg"></param>
|
||||||
|
/// <param name="ex"></param>
|
||||||
|
public static void Info(string type, string msg, Exception ex = null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
msg = $"【类别:{type}】\r\n【内容】:{msg}";
|
||||||
|
if (ex != null)
|
||||||
|
{
|
||||||
|
LogInfo.Info(msg, ex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogInfo.Info(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception err)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
37
MW_Log/Properties/AssemblyInfo.cs
Normal file
37
MW_Log/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// 有关程序集的一般信息由以下
|
||||||
|
// 控制。更改这些特性值可修改
|
||||||
|
// 与程序集关联的信息。
|
||||||
|
[assembly: AssemblyTitle("MW_Log")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("MW_Log")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2023")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||||
|
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||||
|
//请将此类型的 ComVisible 特性设置为 true。
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||||
|
[assembly: Guid("1ac112c4-2400-4d03-a26d-2e3ace6fe6d4")]
|
||||||
|
|
||||||
|
// 程序集的版本信息由下列四个值组成:
|
||||||
|
//
|
||||||
|
// 主版本
|
||||||
|
// 次版本
|
||||||
|
// 生成号
|
||||||
|
// 修订号
|
||||||
|
//
|
||||||
|
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||||
|
//通过使用 "*",如下所示:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||||
|
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", ConfigFileExtension = "config", Watch = true)]
|
||||||
BIN
MW_Log/_codex_verify/MW_Log.dll
Normal file
BIN
MW_Log/_codex_verify/MW_Log.dll
Normal file
Binary file not shown.
35
MW_Log/_codex_verify/log4net.config
Normal file
35
MW_Log/_codex_verify/log4net.config
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<configuration>
|
||||||
|
<configSections>
|
||||||
|
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
|
||||||
|
</configSections>
|
||||||
|
<log4net>
|
||||||
|
<!--Info日志-->
|
||||||
|
<appender name="InfoAppender" type="log4net.Appender.RollingFileAppender">
|
||||||
|
<!--日志文件存放位置,可以为绝对路径也可以为相对路径 -->
|
||||||
|
<param name="File" value="C:\MWLOG" />
|
||||||
|
<!--是否支持分割文件-->
|
||||||
|
<param name="AppendToFile" value="true" />
|
||||||
|
<param name="MaxFileSize" value="10240" />
|
||||||
|
<!--当日志文件达到MaxFileSize大小,就自动创建备份文件。-->
|
||||||
|
<param name="MaxSizeRollBackups" value="100" />
|
||||||
|
<!-- 当将日期作为日志文件的名字时,必须将staticLogFileName的值设置为false -->
|
||||||
|
<param name="StaticLogFileName" value="false" />
|
||||||
|
<!-- 日志文件的命名规则 -->
|
||||||
|
<param name="DatePattern" value="\\yyyy_MM\\yyyy_MM_dd'.log'" />
|
||||||
|
<!--日志文件的记录形式-->
|
||||||
|
<param name="RollingStyle" value="Date" />
|
||||||
|
<!--日志文件的布局格式:%newline【%date】【级别:%-5level】【线程ID:%thread】%n【内容】:%message%newline %n%n-->
|
||||||
|
<layout type="log4net.Layout.PatternLayout">
|
||||||
|
<conversionPattern value="【%date】【线程ID:%thread】%message%newline %n%n" />
|
||||||
|
</layout>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!--Info日志-->
|
||||||
|
<logger name="LogInfo">
|
||||||
|
<level value="INFO" />
|
||||||
|
<appender-ref ref="InfoAppender" />
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
</log4net>
|
||||||
|
</configuration>
|
||||||
BIN
MW_Log/_codex_verify/log4net.dll
Normal file
BIN
MW_Log/_codex_verify/log4net.dll
Normal file
Binary file not shown.
35
MW_Log/log4net.config
Normal file
35
MW_Log/log4net.config
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<configuration>
|
||||||
|
<configSections>
|
||||||
|
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
|
||||||
|
</configSections>
|
||||||
|
<log4net>
|
||||||
|
<!--Info日志-->
|
||||||
|
<appender name="InfoAppender" type="log4net.Appender.RollingFileAppender">
|
||||||
|
<!--日志文件存放位置,可以为绝对路径也可以为相对路径 -->
|
||||||
|
<param name="File" value="C:\MWLOG" />
|
||||||
|
<!--是否支持分割文件-->
|
||||||
|
<param name="AppendToFile" value="true" />
|
||||||
|
<param name="MaxFileSize" value="10240" />
|
||||||
|
<!--当日志文件达到MaxFileSize大小,就自动创建备份文件。-->
|
||||||
|
<param name="MaxSizeRollBackups" value="100" />
|
||||||
|
<!-- 当将日期作为日志文件的名字时,必须将staticLogFileName的值设置为false -->
|
||||||
|
<param name="StaticLogFileName" value="false" />
|
||||||
|
<!-- 日志文件的命名规则 -->
|
||||||
|
<param name="DatePattern" value="\\yyyy_MM\\yyyy_MM_dd'.log'" />
|
||||||
|
<!--日志文件的记录形式-->
|
||||||
|
<param name="RollingStyle" value="Date" />
|
||||||
|
<!--日志文件的布局格式:%newline【%date】【级别:%-5level】【线程ID:%thread】%n【内容】:%message%newline %n%n-->
|
||||||
|
<layout type="log4net.Layout.PatternLayout">
|
||||||
|
<conversionPattern value="【%date】【线程ID:%thread】%message%newline %n%n" />
|
||||||
|
</layout>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!--Info日志-->
|
||||||
|
<logger name="LogInfo">
|
||||||
|
<level value="INFO" />
|
||||||
|
<appender-ref ref="InfoAppender" />
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
</log4net>
|
||||||
|
</configuration>
|
||||||
38
SCADA/App.config
Normal file
38
SCADA/App.config
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<appSettings>
|
||||||
|
<add key="IsDemoMesServer" value="1"/>
|
||||||
|
<add key="BasicDataTableFile" value="SignalTable_CZ.xlsx"/>
|
||||||
|
<add key="IsAllowWrite" value="1"/>
|
||||||
|
<!--是启用写监控报错日志-->
|
||||||
|
<add key="IsWriteMonitorLog" value="0"/>
|
||||||
|
<add key="IsWriteLog4" value="1"/>
|
||||||
|
<!--称重类型:Ground=地面称重(两独立工位), Hanging=空中称重/吊称(放油前+放油后)-->
|
||||||
|
<add key="WeighingType" value="Hanging"/>
|
||||||
|
<!--数据库连接-->
|
||||||
|
<add key="ConnectionString" value="server=.,1333;database=MESBasicDB_WC_CZGKJ;uid=sa;pwd=126.com;Connection Reset=FALSE;Max Pool Size = 1000"/>
|
||||||
|
<!--WebApi-->
|
||||||
|
<add key="WebApi_Port" value="9981"/>
|
||||||
|
|
||||||
|
|
||||||
|
<add key="WebApi_ReqUrl_WMS_Call" value="http://127.0.0.1:9981/api/wms/msgRequest_WMS_Call"/>
|
||||||
|
<add key="WebApi_ReqUrl_WMS_Return" value="http://127.0.0.1:9981/api/wms/msgRequest_WMS_Return"/>
|
||||||
|
<add key="WebUrl_AGV_HK" value=" http://127.0.0.1:9981/api/agv/MES_To_AGV_HK_Continue" />
|
||||||
|
<add key="WebUrl_AGV_HK_CTU" value="http://127.0.0.1:9981/api/agv/MES_To_AGV_HK_CTU" />
|
||||||
|
|
||||||
|
<add key="WebUrl_AGV_HK_agvCallback" value="http://127.0.0.1:9981/api/agv/agvCallback" />
|
||||||
|
|
||||||
|
<!--扫码枪:1=启用, 0=禁用-->
|
||||||
|
<add key="IsUseBarcode" value="0"/>
|
||||||
|
<!--OP10扫码枪COM口,如COM3-->
|
||||||
|
<add key="OP10BarCOM" value="COM2"/>
|
||||||
|
<!--OP20扫码枪COM口,如COM4-->
|
||||||
|
<add key="OP20BarCOM" value="COM3"/>
|
||||||
|
<!--扫码枪波特率-->
|
||||||
|
<add key="BarcodeBaudRate" value="9600"/>
|
||||||
|
|
||||||
|
</appSettings>
|
||||||
|
<startup>
|
||||||
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
|
||||||
|
</startup>
|
||||||
|
</configuration>
|
||||||
317
SCADA/Core/AppConfig.cs
Normal file
317
SCADA/Core/AppConfig.cs
Normal file
@@ -0,0 +1,317 @@
|
|||||||
|
|
||||||
|
using HslCommunication.WebSocket;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using NPOI.POIFS.Properties;
|
||||||
|
using NPOI.SS.Formula.Functions;
|
||||||
|
using OpcBasic;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection.Emit;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using WebApi;
|
||||||
|
using static System.Configuration.ConfigurationManager;
|
||||||
|
|
||||||
|
namespace MesWork
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public partial class Temp {
|
||||||
|
public static MesWorkForm mesWorkForm = null;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 配置信息
|
||||||
|
/// </summary>
|
||||||
|
public partial class MesWorkForm
|
||||||
|
{
|
||||||
|
|
||||||
|
public static int workerThreads = 4000;
|
||||||
|
public static int completionPortThreads = 2000;
|
||||||
|
|
||||||
|
|
||||||
|
public static string BasicDataTableFile = AppSettings["BasicDataTableFile"];
|
||||||
|
public static int IsDemoMesServer = Convert.ToInt32(AppSettings["IsDemoMesServer"]);
|
||||||
|
public static int IsAllowWrite = Convert.ToInt32(AppSettings["IsAllowWrite"]);
|
||||||
|
public static int IsWriteMonitorLog = Convert.ToInt32(AppSettings["IsWriteMonitorLog"]);
|
||||||
|
public static int IsWriteLog4 = Convert.ToInt32(AppSettings["IsWriteLog4"]);
|
||||||
|
public static string ConnectionString = AppSettings["ConnectionString"];
|
||||||
|
|
||||||
|
public static string AuthorizationSet = AppSettings["AuthorizationSet"];
|
||||||
|
|
||||||
|
public static int WebApi_Port = Convert.ToInt32(AppSettings["WebApi_Port"]);
|
||||||
|
|
||||||
|
public static string WebApi_ReqUrl = AppSettings["WebApi_ReqUrl"];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前工位号
|
||||||
|
/// </summary>
|
||||||
|
public static string Curr_Station = AppSettings["Curr_Station"] ?? "";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 称重类型:Ground=地面称重, Hanging=空中称重/吊称
|
||||||
|
/// </summary>
|
||||||
|
public static string WeighingType = AppSettings["WeighingType"] ?? "Hanging";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否启用扫码枪:1=启用, 0=禁用
|
||||||
|
/// </summary>
|
||||||
|
public static int IsUseBarcode = int.TryParse(AppSettings["IsUseBarcode"], out var _iub) ? _iub : 0;
|
||||||
|
/// <summary>
|
||||||
|
/// OP10扫码枪COM口(如COM3),空则不启用
|
||||||
|
/// </summary>
|
||||||
|
public static string OP10BarCOM = AppSettings["OP10BarCOM"] ?? "";
|
||||||
|
/// <summary>
|
||||||
|
/// OP20扫码枪COM口(如COM4),空则不启用
|
||||||
|
/// </summary>
|
||||||
|
public static string OP20BarCOM = AppSettings["OP20BarCOM"] ?? "";
|
||||||
|
/// <summary>
|
||||||
|
/// 扫码枪波特率
|
||||||
|
/// </summary>
|
||||||
|
public static int BarcodeBaudRate = int.TryParse(AppSettings["BarcodeBaudRate"], out var _bbr) ? _bbr : 9600;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设备工位名称列表(如 OP10, OP20),在OnStart中从设备表加载
|
||||||
|
/// </summary>
|
||||||
|
public static System.Collections.Generic.List<string> StationOpNames = new System.Collections.Generic.List<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 工位显示名称映射(opName → "OP10 — 称重位1"),在OnStart中从设备表加载
|
||||||
|
/// </summary>
|
||||||
|
public static System.Collections.Generic.Dictionary<string, string> StationDisplayNames
|
||||||
|
= new System.Collections.Generic.Dictionary<string, string>(System.StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 称重作业页面实例引用,供MIS_Funtion推送交互消息
|
||||||
|
/// </summary>
|
||||||
|
public static Pages.UC_Weighing WeighingPage;
|
||||||
|
|
||||||
|
public static Color color_Faw = Color.FromArgb(0, 44, 101);//蓝色,大众:0,44,101
|
||||||
|
public static Color color_Good = Color.FromArgb(132, 185, 235);//浅蓝,自定义
|
||||||
|
public static Color color_Wait = Color.FromArgb(240, 230, 140);//淡黄,显示等待状态
|
||||||
|
public static Color color_Bad = SystemColors.ActiveBorder;//灰色,显示操作过程
|
||||||
|
public static Color color_Grey = Color.FromArgb(192, 192, 192);//灰色,Table底色
|
||||||
|
|
||||||
|
public static Color color_Green = Color.FromArgb(22, 161, 136);//绿色
|
||||||
|
public static Color color_Yellow = Color.FromArgb(246, 227, 74);//黄色
|
||||||
|
public static Color color_Red = Color.FromArgb(255, 0, 0);//红色
|
||||||
|
|
||||||
|
public static Color color_Blue_FJ = Color.FromArgb(19, 34, 122);//深蓝
|
||||||
|
public static Color color_White_FJ = Color.White;//白色
|
||||||
|
public static Color color_Control = SystemColors.Control;//控件默认颜色
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static bool OnLine_Sql = false;
|
||||||
|
|
||||||
|
public static string Curr_UserName = "";
|
||||||
|
public static string Curr_LoginID = "";
|
||||||
|
public static string Curr_UserPassWord = "";
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WebApi
|
||||||
|
/// </summary>
|
||||||
|
public static InitServer initServer = null;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 监控数据的所有变化,从这里产生
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
public override void OPCTagData_TagDataOnChangeMIS(object sender, DeviceDriver_BasicData.CustomeEvetnArgs e)
|
||||||
|
{
|
||||||
|
ThreadPool.QueueUserWorkItem(new WaitCallback(MIS_Funtion), e);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 定时触发,检测PLC在线状态,周期:3 s
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="eState"></param>
|
||||||
|
public override void PlcStateEvent(object sender, DeviceDriver_BasicData.PlcStateEvetnArgs eState)
|
||||||
|
{
|
||||||
|
ThreadPool.QueueUserWorkItem(new WaitCallback(MIS_Device), eState);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="t"></param>
|
||||||
|
/// <param name="location"></param>
|
||||||
|
/// <param name="content"></param>
|
||||||
|
public override void E_WriteLog(Enum_LogType t, string location, string content)
|
||||||
|
{
|
||||||
|
if (content .Contains("GetTagIDByTagTypeCodeID(),"))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
WriteLog_Info(t.ToString(), $"<[<{location}>]>{content}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[STAThread]
|
||||||
|
static void Main()
|
||||||
|
{
|
||||||
|
new System.Threading.Mutex(true, $"MES_PWT_A95", out bool bCanRun);
|
||||||
|
if (!bCanRun)
|
||||||
|
{
|
||||||
|
MessageBox.Show("MES采集系统 已经在运行!不可重复启动!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Application.EnableVisualStyles();
|
||||||
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
Application.Run(Temp.mesWorkForm = new MesWorkForm());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string Hello_You_All_Never_Know(string[] args)
|
||||||
|
{
|
||||||
|
return Guid.NewGuid().ToString() + Guid.NewGuid().ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写入信号
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tagTypeCodeID"></param>
|
||||||
|
/// <param name="ststionName"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
public static void WritePLC_IF(int tagTypeCodeID,string ststionName,object value)
|
||||||
|
{
|
||||||
|
if (IsAllowWrite == 1)
|
||||||
|
{
|
||||||
|
WritePLC(tagTypeCodeID, ststionName, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写日志
|
||||||
|
/// 2023.10.30.llx
|
||||||
|
/// </summary>
|
||||||
|
public static void WriteLog_Info(string type, string msg, Exception ex = null)
|
||||||
|
{
|
||||||
|
if (IsWriteLog4 == 1)
|
||||||
|
{
|
||||||
|
MW_Log.LoggerHelper.Info(type, msg, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CommunicationCheckOnLine()
|
||||||
|
{
|
||||||
|
|
||||||
|
new Thread(new ThreadStart(delegate ()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MesWorkForm.OnLine_Sql = DataLinkMesWork.SQLCommon.ExecuteDataTable("select getdate()", ConnectionString, out DataTable dt, out string err);
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
Thread.Sleep(5000);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
{ IsBackground = true }.Start();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void Loop_SelectAlarmShow()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
B_DB_Opera.Query_AlarmData(Curr_Station, out int count, out string text);
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
label_Alarm.Text = $"({count}) {text}";
|
||||||
|
panel_Alarm.BackColor = Color.Red;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
label_Alarm.Text = $"";
|
||||||
|
panel_Alarm.BackColor = Color.FromArgb(30, 58, 95);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception err)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Loop_ReadRealPageShow 已移除(旧UI控件引用),PLC信号显示将在 UC_Weighing 中实现
|
||||||
|
|
||||||
|
public void ShowSignal(Control c,string opName)
|
||||||
|
{
|
||||||
|
if (!c.Name.Contains("_Show_"))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var tagTypeCodeID = Convert.ToInt32(c.Name.Split('_')[3]);
|
||||||
|
if (c is TextBox)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
c.Text = PlcLinkForm.ReadPLC(tagTypeCodeID, opName).ToString();
|
||||||
|
}
|
||||||
|
catch (Exception err)
|
||||||
|
{
|
||||||
|
c.Text = "不存在该信号!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void ShowSignal(Control c, int tagTypeCodeID, string opName)
|
||||||
|
{
|
||||||
|
if (c is Panel)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
c.BackColor = PlcLinkForm.ReadPLC(tagTypeCodeID, opName).ToString().ToLower().Replace("true", "1").Replace("false", "0") == "1" ? Color.Lime : color_Grey;
|
||||||
|
}
|
||||||
|
catch (Exception err)
|
||||||
|
{
|
||||||
|
c.BackColor = color_Grey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConcurrentDictionary<string, TagFormat> ReadPLC_OpName(string opName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var res = new ConcurrentDictionary<string, TagFormat>();
|
||||||
|
var tagAdrListTagFormat0 = PlcLinkForm.ReadPLC_GroupData_SingleTag(opName);
|
||||||
|
foreach (var item in tagAdrListTagFormat0)
|
||||||
|
{
|
||||||
|
var key = item.Key;
|
||||||
|
var value = (TagFormat)item.Value;
|
||||||
|
res.TryAdd(key, value);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
catch (Exception err)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
107
SCADA/Core/BarcodeManager.cs
Normal file
107
SCADA/Core/BarcodeManager.cs
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace MesWork
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 扫码枪管理器 — 管理最多2把扫码枪的生命周期和事件分发
|
||||||
|
/// </summary>
|
||||||
|
public static class BarcodeManager
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 扫码枪实例字典,key = opName(OP10/OP20)
|
||||||
|
/// </summary>
|
||||||
|
public static Dictionary<string, BarcodeScanner> Scanners { get; } = new Dictionary<string, BarcodeScanner>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否启用扫码枪功能
|
||||||
|
/// </summary>
|
||||||
|
public static bool IsEnabled => MesWorkForm.IsUseBarcode == 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扫码事件回调(由外部设置,通常指向 MIS_Funtion 的处理方法)
|
||||||
|
/// </summary>
|
||||||
|
public static Action<string, string> OnBarcodeScanned;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化扫码枪(读取配置并创建实例)
|
||||||
|
/// </summary>
|
||||||
|
public static void Init()
|
||||||
|
{
|
||||||
|
if (!IsEnabled) return;
|
||||||
|
|
||||||
|
int baudRate = MesWorkForm.BarcodeBaudRate;
|
||||||
|
|
||||||
|
// OP10
|
||||||
|
string op10Com = MesWorkForm.OP10BarCOM?.Trim();
|
||||||
|
if (!string.IsNullOrEmpty(op10Com))
|
||||||
|
{
|
||||||
|
var scanner = new BarcodeScanner("OP10", baudRate);
|
||||||
|
scanner.BarcodeReceived += HandleBarcodeReceived;
|
||||||
|
scanner.Log += HandleLog;
|
||||||
|
Scanners["OP10"] = scanner;
|
||||||
|
scanner.Connect(op10Com);
|
||||||
|
}
|
||||||
|
|
||||||
|
// OP20
|
||||||
|
string op20Com = MesWorkForm.OP20BarCOM?.Trim();
|
||||||
|
if (!string.IsNullOrEmpty(op20Com))
|
||||||
|
{
|
||||||
|
var scanner = new BarcodeScanner("OP20", baudRate);
|
||||||
|
scanner.BarcodeReceived += HandleBarcodeReceived;
|
||||||
|
scanner.Log += HandleLog;
|
||||||
|
Scanners["OP20"] = scanner;
|
||||||
|
scanner.Connect(op20Com);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 统一扫码事件处理
|
||||||
|
/// </summary>
|
||||||
|
private static void HandleBarcodeReceived(string opName, string barcode)
|
||||||
|
{
|
||||||
|
OnBarcodeScanned?.Invoke(opName, barcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扫码枪日志 → 系统日志 + 称重页面
|
||||||
|
/// </summary>
|
||||||
|
private static void HandleLog(string message)
|
||||||
|
{
|
||||||
|
MesWorkForm.WriteLog_Info("BarcodeScanner", message);
|
||||||
|
MesWorkForm.WeighingPage?.AppendLog(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 手动发送条码(模拟扫码触发)
|
||||||
|
/// </summary>
|
||||||
|
public static void ManualSend(string opName, string barcode)
|
||||||
|
{
|
||||||
|
// 直接走事件回调,和自动扫码一样的路径
|
||||||
|
if (!string.IsNullOrWhiteSpace(barcode))
|
||||||
|
HandleBarcodeReceived(opName, barcode.Trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 释放所有扫码枪
|
||||||
|
/// </summary>
|
||||||
|
public static void Shutdown()
|
||||||
|
{
|
||||||
|
foreach (var scanner in Scanners.Values)
|
||||||
|
{
|
||||||
|
try { scanner.Dispose(); } catch { }
|
||||||
|
}
|
||||||
|
Scanners.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有可用COM口
|
||||||
|
/// </summary>
|
||||||
|
public static string[] GetAvailablePorts()
|
||||||
|
{
|
||||||
|
try { return System.IO.Ports.SerialPort.GetPortNames(); }
|
||||||
|
catch { return new string[0]; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
323
SCADA/Core/BarcodeScanner.cs
Normal file
323
SCADA/Core/BarcodeScanner.cs
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO.Ports;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MesWork
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 单把扫码枪的串口通信封装
|
||||||
|
/// 包含数据接收(缓冲+空闲提交)、防抖、断线自动重连
|
||||||
|
/// </summary>
|
||||||
|
public class BarcodeScanner : IDisposable
|
||||||
|
{
|
||||||
|
// ── 基本属性 ──
|
||||||
|
/// <summary>关联工位号(OP10/OP20)</summary>
|
||||||
|
public string OpName { get; }
|
||||||
|
|
||||||
|
/// <summary>当前COM口</summary>
|
||||||
|
public string ComPort { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>是否已连接</summary>
|
||||||
|
public bool IsConnected
|
||||||
|
{
|
||||||
|
get { try { return _serial != null && _serial.IsOpen; } catch { return false; } }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>最近一次扫到的条码</summary>
|
||||||
|
public string LastBarcode { get; private set; } = "";
|
||||||
|
|
||||||
|
/// <summary>最近一次扫码时间</summary>
|
||||||
|
public DateTime? LastScanTime { get; private set; }
|
||||||
|
|
||||||
|
// ── 事件 ──
|
||||||
|
/// <summary>扫码完成事件(opName, barcode)</summary>
|
||||||
|
public event Action<string, string> BarcodeReceived;
|
||||||
|
|
||||||
|
/// <summary>日志事件(message),由外部接入系统日志</summary>
|
||||||
|
public event Action<string> Log;
|
||||||
|
|
||||||
|
// ── 私有字段 ──
|
||||||
|
private SerialPort _serial;
|
||||||
|
private readonly int _baudRate;
|
||||||
|
private readonly object _bufferLock = new object();
|
||||||
|
private readonly StringBuilder _buffer = new StringBuilder(256);
|
||||||
|
private System.Windows.Forms.Timer _flushTimer;
|
||||||
|
private const int FlushIntervalMs = 60;
|
||||||
|
|
||||||
|
// 防抖
|
||||||
|
private string _lastDebounceCode = "";
|
||||||
|
private DateTime _lastDebounceTime = DateTime.MinValue;
|
||||||
|
private const int DebounceMs = 500;
|
||||||
|
|
||||||
|
// 断线重连
|
||||||
|
private System.Windows.Forms.Timer _reconnectTimer;
|
||||||
|
private volatile bool _reconnecting = false;
|
||||||
|
private bool _disposed = false;
|
||||||
|
|
||||||
|
public BarcodeScanner(string opName, int baudRate = 9600)
|
||||||
|
{
|
||||||
|
OpName = opName;
|
||||||
|
_baudRate = baudRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 连接指定COM口
|
||||||
|
/// </summary>
|
||||||
|
public bool Connect(string comPort)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(comPort) || comPort.Length < 3)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Disconnect();
|
||||||
|
ComPort = comPort;
|
||||||
|
|
||||||
|
_serial = new SerialPort
|
||||||
|
{
|
||||||
|
PortName = comPort,
|
||||||
|
BaudRate = _baudRate,
|
||||||
|
Parity = Parity.None,
|
||||||
|
StopBits = StopBits.One,
|
||||||
|
ReadTimeout = 1000,
|
||||||
|
DtrEnable = true
|
||||||
|
};
|
||||||
|
_serial.DataReceived += Serial_DataReceived;
|
||||||
|
_serial.Open();
|
||||||
|
|
||||||
|
// 空闲提交定时器
|
||||||
|
if (_flushTimer == null)
|
||||||
|
{
|
||||||
|
_flushTimer = new System.Windows.Forms.Timer { Interval = FlushIntervalMs };
|
||||||
|
_flushTimer.Tick += FlushTimer_Tick;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 断线重连定时器(每3秒检测)
|
||||||
|
if (_reconnectTimer == null)
|
||||||
|
{
|
||||||
|
_reconnectTimer = new System.Windows.Forms.Timer { Interval = 3000 };
|
||||||
|
_reconnectTimer.Tick += ReconnectTimer_Tick;
|
||||||
|
}
|
||||||
|
_reconnectTimer.Start();
|
||||||
|
|
||||||
|
Log?.Invoke($"[{OpName}] 扫码枪已连接 ({comPort})");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log?.Invoke($"[{OpName}] 扫码枪连接失败 ({comPort}):{ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 断开连接
|
||||||
|
/// </summary>
|
||||||
|
public void Disconnect()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_reconnectTimer?.Stop();
|
||||||
|
_flushTimer?.Stop();
|
||||||
|
|
||||||
|
if (_serial != null)
|
||||||
|
{
|
||||||
|
_serial.DataReceived -= Serial_DataReceived;
|
||||||
|
if (_serial.IsOpen) _serial.Close();
|
||||||
|
_serial.Dispose();
|
||||||
|
_serial = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 测试当前COM口是否可连接
|
||||||
|
/// </summary>
|
||||||
|
public bool TestConnection(string comPort)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var sp = new SerialPort(comPort, _baudRate))
|
||||||
|
{
|
||||||
|
sp.Open();
|
||||||
|
sp.Close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 串口数据接收 ──
|
||||||
|
private void Serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_serial == null || !_serial.IsOpen) return;
|
||||||
|
|
||||||
|
int bytesToRead = _serial.BytesToRead;
|
||||||
|
if (bytesToRead <= 0) return;
|
||||||
|
|
||||||
|
byte[] buf = new byte[bytesToRead];
|
||||||
|
_serial.Read(buf, 0, bytesToRead);
|
||||||
|
string chunk = Encoding.UTF8.GetString(buf, 0, bytesToRead);
|
||||||
|
|
||||||
|
lock (_bufferLock)
|
||||||
|
{
|
||||||
|
_buffer.Append(chunk);
|
||||||
|
string acc = _buffer.ToString();
|
||||||
|
|
||||||
|
// 按换行符(\r \n)拆分完整条码
|
||||||
|
int startIndex = 0;
|
||||||
|
for (int i = 0; i < acc.Length; i++)
|
||||||
|
{
|
||||||
|
if (acc[i] == '\r' || acc[i] == '\n')
|
||||||
|
{
|
||||||
|
int len = i - startIndex;
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
string line = acc.Substring(startIndex, len).Trim();
|
||||||
|
if (!string.IsNullOrEmpty(line))
|
||||||
|
SubmitBarcode(line);
|
||||||
|
}
|
||||||
|
startIndex = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startIndex >= acc.Length)
|
||||||
|
_buffer.Clear();
|
||||||
|
else if (startIndex > 0)
|
||||||
|
{
|
||||||
|
_buffer.Clear();
|
||||||
|
_buffer.Append(acc.Substring(startIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 无换行 → 启动空闲定时器
|
||||||
|
if (_buffer.Length > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_flushTimer?.Stop();
|
||||||
|
_flushTimer?.Start();
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (ex is System.IO.IOException || ex is InvalidOperationException)
|
||||||
|
{
|
||||||
|
Log?.Invoke($"[{OpName}] 扫码枪通信异常,尝试重连:{ex.Message}");
|
||||||
|
TryReopen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
try { _serial?.DiscardInBuffer(); } catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 空闲超时提交缓冲区
|
||||||
|
private void FlushTimer_Tick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_flushTimer.Stop();
|
||||||
|
string toSend;
|
||||||
|
lock (_bufferLock)
|
||||||
|
{
|
||||||
|
toSend = _buffer.ToString().Trim();
|
||||||
|
_buffer.Clear();
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(toSend))
|
||||||
|
SubmitBarcode(toSend);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交条码(含防抖)
|
||||||
|
private void SubmitBarcode(string barcode)
|
||||||
|
{
|
||||||
|
barcode = barcode.Replace("\r", "").Replace("\n", "").Replace("\0", "").Trim();
|
||||||
|
if (string.IsNullOrEmpty(barcode)) return;
|
||||||
|
|
||||||
|
// 防抖
|
||||||
|
var now = DateTime.Now;
|
||||||
|
if (barcode == _lastDebounceCode && (now - _lastDebounceTime).TotalMilliseconds < DebounceMs)
|
||||||
|
return;
|
||||||
|
_lastDebounceCode = barcode;
|
||||||
|
_lastDebounceTime = now;
|
||||||
|
|
||||||
|
// 更新状态
|
||||||
|
LastBarcode = barcode;
|
||||||
|
LastScanTime = now;
|
||||||
|
|
||||||
|
// 触发事件
|
||||||
|
BarcodeReceived?.Invoke(OpName, barcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 手动发送条码(模拟扫码触发,走完整业务流程)
|
||||||
|
/// </summary>
|
||||||
|
public void ManualSend(string barcode)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(barcode))
|
||||||
|
SubmitBarcode(barcode.Trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 断线重连 ──
|
||||||
|
private void ReconnectTimer_Tick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (_reconnecting || string.IsNullOrWhiteSpace(ComPort)) return;
|
||||||
|
if (IsConnected) return;
|
||||||
|
|
||||||
|
_reconnecting = true;
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
try { TryReopen(); }
|
||||||
|
catch { }
|
||||||
|
finally { _reconnecting = false; }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TryReopen()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string[] ports = SerialPort.GetPortNames();
|
||||||
|
bool exists = Array.Exists(ports, p => string.Equals(p, ComPort, StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (!exists) return;
|
||||||
|
|
||||||
|
if (_serial != null)
|
||||||
|
{
|
||||||
|
try { if (_serial.IsOpen) _serial.Close(); } catch { }
|
||||||
|
try { _serial.Dispose(); } catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
_serial = new SerialPort
|
||||||
|
{
|
||||||
|
PortName = ComPort,
|
||||||
|
BaudRate = _baudRate,
|
||||||
|
Parity = Parity.None,
|
||||||
|
StopBits = StopBits.One,
|
||||||
|
ReadTimeout = 1000,
|
||||||
|
DtrEnable = true
|
||||||
|
};
|
||||||
|
_serial.DataReceived += Serial_DataReceived;
|
||||||
|
_serial.Open();
|
||||||
|
Log?.Invoke($"[{OpName}] 扫码枪自动重连成功 ({ComPort})");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log?.Invoke($"[{OpName}] 扫码枪自动重连失败 ({ComPort}):{ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_disposed) return;
|
||||||
|
_disposed = true;
|
||||||
|
Disconnect();
|
||||||
|
_flushTimer?.Dispose();
|
||||||
|
_reconnectTimer?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
SCADA/Core/IconHelper.cs
Normal file
40
SCADA/Core/IconHelper.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace MesWork
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 窗口图标加载工具类(多路径搜索 + exe回退)
|
||||||
|
/// </summary>
|
||||||
|
public static class IconHelper
|
||||||
|
{
|
||||||
|
private static readonly string[] IconSearchPaths = new[]
|
||||||
|
{
|
||||||
|
System.IO.Path.Combine(Application.StartupPath, "任务管理.ico"),
|
||||||
|
System.IO.Path.Combine(System.IO.Path.GetDirectoryName(
|
||||||
|
System.Reflection.Assembly.GetExecutingAssembly().Location) ?? "", "任务管理.ico"),
|
||||||
|
"任务管理.ico"
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 为指定窗体加载图标
|
||||||
|
/// </summary>
|
||||||
|
public static void ApplyIcon(Form form)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (var path in IconSearchPaths)
|
||||||
|
{
|
||||||
|
if (System.IO.File.Exists(path))
|
||||||
|
{
|
||||||
|
form.Icon = new Icon(path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
form.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
626
SCADA/Core/OExcel.cs
Normal file
626
SCADA/Core/OExcel.cs
Normal file
@@ -0,0 +1,626 @@
|
|||||||
|
using NPOI.HPSF;
|
||||||
|
using NPOI.HSSF.UserModel;
|
||||||
|
using NPOI.SS.UserModel;
|
||||||
|
using NPOI.XSSF.UserModel;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NPOITest
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execl工具辅助类
|
||||||
|
/// </summary>
|
||||||
|
public class ExeclHelper
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取Execl数据到DataTable中
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filePath">指定Execl文件路径</param>
|
||||||
|
/// <param name="isColumnName">设置第一行是否是列名</param>
|
||||||
|
/// <returns>返回一个DataTable数据集</returns>
|
||||||
|
public static DataTable ExcelToDataTable(string filePath, string sheetName, bool isColumnName)
|
||||||
|
{
|
||||||
|
DataTable dataTable = null;
|
||||||
|
FileStream fs = null;
|
||||||
|
DataColumn column = null;
|
||||||
|
DataRow dataRow = null;
|
||||||
|
IWorkbook workbook = null;
|
||||||
|
ISheet sheet = null;
|
||||||
|
IRow row = null;
|
||||||
|
ICell cell = null;
|
||||||
|
int startRow = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||||
|
{
|
||||||
|
// 2007版本
|
||||||
|
if (filePath.IndexOf(".xlsx") > 0)
|
||||||
|
workbook = new XSSFWorkbook(fs);
|
||||||
|
// 2003版本
|
||||||
|
else if (filePath.IndexOf(".xls") > 0)
|
||||||
|
workbook = new HSSFWorkbook(fs);
|
||||||
|
if (workbook != null)
|
||||||
|
{
|
||||||
|
sheet = workbook.GetSheet(sheetName);//读取第一个sheet,当然也可以循环读取每个sheet
|
||||||
|
dataTable = new DataTable();
|
||||||
|
if (sheet != null)
|
||||||
|
{
|
||||||
|
int rowCount = sheet.LastRowNum;//总行数
|
||||||
|
if (rowCount > 0)
|
||||||
|
{
|
||||||
|
IRow firstRow = sheet.GetRow(0);//第一行
|
||||||
|
int cellCount = firstRow.LastCellNum;//列数
|
||||||
|
|
||||||
|
//构建datatable的列
|
||||||
|
if (isColumnName)
|
||||||
|
{
|
||||||
|
startRow = 1;//如果第一行是列名,则从第二行开始读取
|
||||||
|
for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
|
||||||
|
{
|
||||||
|
cell = firstRow.GetCell(i);
|
||||||
|
if (cell != null)
|
||||||
|
{
|
||||||
|
if (cell.StringCellValue != null)
|
||||||
|
{
|
||||||
|
column = new DataColumn(cell.StringCellValue);
|
||||||
|
dataTable.Columns.Add(column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
|
||||||
|
{
|
||||||
|
column = new DataColumn("column" + (i + 1));
|
||||||
|
dataTable.Columns.Add(column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//填充行
|
||||||
|
for (int i = startRow; i <= rowCount; ++i)
|
||||||
|
{
|
||||||
|
row = sheet.GetRow(i);
|
||||||
|
if (row == null) continue;
|
||||||
|
|
||||||
|
dataRow = dataTable.NewRow();
|
||||||
|
for (int j = row.FirstCellNum; j < cellCount; ++j)
|
||||||
|
{
|
||||||
|
cell = row.GetCell(j);
|
||||||
|
if (cell == null)
|
||||||
|
{
|
||||||
|
dataRow[j] = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//CellType(Unknown = -1,Numeric = 0,String = 1,Formula = 2,Blank = 3,Boolean = 4,Error = 5,)
|
||||||
|
switch (cell.CellType)
|
||||||
|
{
|
||||||
|
case CellType.Blank:
|
||||||
|
dataRow[j] = "";
|
||||||
|
break;
|
||||||
|
case CellType.Numeric:
|
||||||
|
short format = cell.CellStyle.DataFormat;
|
||||||
|
//对时间格式(2015.12.5、2015/12/5、2015-12-5等)的处理
|
||||||
|
if (format == 14 || format == 31 || format == 57 || format == 58)
|
||||||
|
dataRow[j] = cell.DateCellValue;
|
||||||
|
else
|
||||||
|
dataRow[j] = cell.NumericCellValue;
|
||||||
|
break;
|
||||||
|
case CellType.String:
|
||||||
|
dataRow[j] = cell.StringCellValue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataTable.Rows.Add(dataRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dataTable;
|
||||||
|
}
|
||||||
|
catch (Exception err)
|
||||||
|
{
|
||||||
|
if (fs != null)
|
||||||
|
{
|
||||||
|
fs.Close();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DataTable ExcelToDataTable(string filePath,int sheetIndex, bool isColumnName)
|
||||||
|
{
|
||||||
|
DataTable dataTable = null;
|
||||||
|
FileStream fs = null;
|
||||||
|
DataColumn column = null;
|
||||||
|
DataRow dataRow = null;
|
||||||
|
IWorkbook workbook = null;
|
||||||
|
ISheet sheet = null;
|
||||||
|
IRow row = null;
|
||||||
|
ICell cell = null;
|
||||||
|
int startRow = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||||
|
{
|
||||||
|
// 2007版本
|
||||||
|
if (filePath.IndexOf(".xlsx") > 0)
|
||||||
|
workbook = new XSSFWorkbook(fs);
|
||||||
|
// 2003版本
|
||||||
|
else if (filePath.IndexOf(".xls") > 0)
|
||||||
|
workbook = new HSSFWorkbook(fs);
|
||||||
|
if (workbook != null)
|
||||||
|
{
|
||||||
|
sheet = workbook.GetSheetAt(sheetIndex);//读取第一个sheet,当然也可以循环读取每个sheet
|
||||||
|
dataTable = new DataTable();
|
||||||
|
if (sheet != null)
|
||||||
|
{
|
||||||
|
int rowCount = sheet.LastRowNum;//总行数
|
||||||
|
if (rowCount > 0)
|
||||||
|
{
|
||||||
|
IRow firstRow = sheet.GetRow(0);//第一行
|
||||||
|
int cellCount = firstRow.LastCellNum;//列数
|
||||||
|
|
||||||
|
//构建datatable的列
|
||||||
|
if (isColumnName)
|
||||||
|
{
|
||||||
|
startRow = 1;//如果第一行是列名,则从第二行开始读取
|
||||||
|
for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
|
||||||
|
{
|
||||||
|
cell = firstRow.GetCell(i);
|
||||||
|
if (cell != null)
|
||||||
|
{
|
||||||
|
if (cell.StringCellValue != null)
|
||||||
|
{
|
||||||
|
column = new DataColumn(cell.StringCellValue);
|
||||||
|
dataTable.Columns.Add(column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
|
||||||
|
{
|
||||||
|
column = new DataColumn("column" + (i + 1));
|
||||||
|
dataTable.Columns.Add(column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//填充行
|
||||||
|
for (int i = startRow; i <= rowCount; ++i)
|
||||||
|
{
|
||||||
|
row = sheet.GetRow(i);
|
||||||
|
if (row == null) continue;
|
||||||
|
|
||||||
|
dataRow = dataTable.NewRow();
|
||||||
|
for (int j = row.FirstCellNum; j < cellCount; ++j)
|
||||||
|
{
|
||||||
|
cell = row.GetCell(j);
|
||||||
|
if (cell == null)
|
||||||
|
{
|
||||||
|
dataRow[j] = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//CellType(Unknown = -1,Numeric = 0,String = 1,Formula = 2,Blank = 3,Boolean = 4,Error = 5,)
|
||||||
|
switch (cell.CellType)
|
||||||
|
{
|
||||||
|
case CellType.Blank:
|
||||||
|
dataRow[j] = "";
|
||||||
|
break;
|
||||||
|
case CellType.Numeric:
|
||||||
|
short format = cell.CellStyle.DataFormat;
|
||||||
|
//对时间格式(2015.12.5、2015/12/5、2015-12-5等)的处理
|
||||||
|
if (format == 14 || format == 31 || format == 57 || format == 58 || format == 22)
|
||||||
|
dataRow[j] = cell.DateCellValue;
|
||||||
|
else
|
||||||
|
dataRow[j] = cell.NumericCellValue;
|
||||||
|
break;
|
||||||
|
case CellType.String:
|
||||||
|
dataRow[j] = cell.StringCellValue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataTable.Rows.Add(dataRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dataTable;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
if (fs != null)
|
||||||
|
{
|
||||||
|
fs.Close();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void DataTableToExcel(DataTable dataTable, string templatePath, string outputPath, int startRow, int startCol)
|
||||||
|
{
|
||||||
|
// 加载模板文件
|
||||||
|
using (FileStream fs = new FileStream(templatePath, FileMode.Open, FileAccess.Read))
|
||||||
|
{
|
||||||
|
IWorkbook workbook = new XSSFWorkbook(fs);
|
||||||
|
ISheet sheet = workbook.GetSheetAt(0); // 获取第一个工作表
|
||||||
|
// 创建单元格样式
|
||||||
|
ICellStyle cellStyle = workbook.CreateCellStyle();
|
||||||
|
IFont font = workbook.CreateFont();
|
||||||
|
font.FontHeightInPoints = 12;
|
||||||
|
cellStyle.SetFont(font);
|
||||||
|
cellStyle.BorderTop = BorderStyle.Thin;
|
||||||
|
cellStyle.BorderBottom = BorderStyle.Thin;
|
||||||
|
cellStyle.BorderLeft = BorderStyle.Thin;
|
||||||
|
cellStyle.BorderRight = BorderStyle.Thin;
|
||||||
|
cellStyle.Alignment = HorizontalAlignment.Center;
|
||||||
|
// 遍历DataTable的每一行
|
||||||
|
for (int i = 0; i < dataTable.Rows.Count; i++)
|
||||||
|
{
|
||||||
|
IRow row = sheet.CreateRow(startRow + i); // 创建新行
|
||||||
|
|
||||||
|
// 遍历DataTable的每一列
|
||||||
|
for (int j = 0; j < dataTable.Columns.Count; j++)
|
||||||
|
{
|
||||||
|
ICell cell = row.CreateCell(startCol + j); // 创建新单元格
|
||||||
|
cell.SetCellValue(dataTable.Rows[i][j].ToString());
|
||||||
|
cell.CellStyle = cellStyle; // 应用单元格样式
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存输出文件
|
||||||
|
using (FileStream outputStream = new FileStream(outputPath, FileMode.Create, FileAccess.Write))
|
||||||
|
{
|
||||||
|
workbook.Write(outputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 将DataTable导出到Excel文档(自动根据扩展名选择 .xlsx / .xls 格式)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dt">传入一个DataTable数据集</param>
|
||||||
|
/// <param name="sheetName">工作表名称</param>
|
||||||
|
/// <param name="Outpath">导出文件完整路径(支持 .xlsx 和 .xls)</param>
|
||||||
|
/// <returns>True表示导出成功,False表示导出失败</returns>
|
||||||
|
public static bool DataTableToExcel(DataTable dt, string sheetName, string Outpath)
|
||||||
|
{
|
||||||
|
if (dt == null || dt.Rows.Count == 0 || string.IsNullOrWhiteSpace(Outpath))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
IWorkbook workbook = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// ── 1. 根据文件扩展名选择正确的 Workbook 类型 ──
|
||||||
|
string ext = Path.GetExtension(Outpath).ToLowerInvariant();
|
||||||
|
if (ext == ".xlsx")
|
||||||
|
workbook = new XSSFWorkbook(); // OOXML 格式
|
||||||
|
else
|
||||||
|
workbook = new HSSFWorkbook(); // BIFF8 格式
|
||||||
|
|
||||||
|
ISheet sheet = workbook.CreateSheet(sheetName);
|
||||||
|
int rowCount = dt.Rows.Count;
|
||||||
|
int columnCount = dt.Columns.Count;
|
||||||
|
|
||||||
|
// ── 2. 创建表头样式(加粗 + 背景色 + 边框) ──
|
||||||
|
ICellStyle headerStyle = workbook.CreateCellStyle();
|
||||||
|
IFont headerFont = workbook.CreateFont();
|
||||||
|
headerFont.IsBold = true;
|
||||||
|
headerFont.FontHeightInPoints = 11;
|
||||||
|
headerFont.FontName = "微软雅黑";
|
||||||
|
headerStyle.SetFont(headerFont);
|
||||||
|
headerStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Grey25Percent.Index;
|
||||||
|
headerStyle.FillPattern = FillPattern.SolidForeground;
|
||||||
|
headerStyle.Alignment = HorizontalAlignment.Center;
|
||||||
|
headerStyle.VerticalAlignment = VerticalAlignment.Center;
|
||||||
|
headerStyle.BorderTop = BorderStyle.Thin;
|
||||||
|
headerStyle.BorderBottom = BorderStyle.Thin;
|
||||||
|
headerStyle.BorderLeft = BorderStyle.Thin;
|
||||||
|
headerStyle.BorderRight = BorderStyle.Thin;
|
||||||
|
|
||||||
|
// ── 3. 创建数据行样式(边框) ──
|
||||||
|
ICellStyle dataStyle = workbook.CreateCellStyle();
|
||||||
|
IFont dataFont = workbook.CreateFont();
|
||||||
|
dataFont.FontHeightInPoints = 10;
|
||||||
|
dataFont.FontName = "微软雅黑";
|
||||||
|
dataStyle.SetFont(dataFont);
|
||||||
|
dataStyle.VerticalAlignment = VerticalAlignment.Center;
|
||||||
|
dataStyle.BorderTop = BorderStyle.Thin;
|
||||||
|
dataStyle.BorderBottom = BorderStyle.Thin;
|
||||||
|
dataStyle.BorderLeft = BorderStyle.Thin;
|
||||||
|
dataStyle.BorderRight = BorderStyle.Thin;
|
||||||
|
|
||||||
|
// ── 4. 写入列头 ──
|
||||||
|
IRow headerRow = sheet.CreateRow(0);
|
||||||
|
headerRow.HeightInPoints = 22;
|
||||||
|
for (int c = 0; c < columnCount; c++)
|
||||||
|
{
|
||||||
|
ICell cell = headerRow.CreateCell(c);
|
||||||
|
cell.SetCellValue(dt.Columns[c].ColumnName);
|
||||||
|
cell.CellStyle = headerStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 5. 写入数据行 ──
|
||||||
|
for (int i = 0; i < rowCount; i++)
|
||||||
|
{
|
||||||
|
IRow row = sheet.CreateRow(i + 1);
|
||||||
|
for (int j = 0; j < columnCount; j++)
|
||||||
|
{
|
||||||
|
ICell cell = row.CreateCell(j);
|
||||||
|
object val = dt.Rows[i][j];
|
||||||
|
// 根据数据类型设置单元格值,保留数值精度
|
||||||
|
if (val == null || val == DBNull.Value)
|
||||||
|
{
|
||||||
|
cell.SetCellValue("");
|
||||||
|
}
|
||||||
|
else if (val is DateTime dtVal)
|
||||||
|
{
|
||||||
|
cell.SetCellValue(dtVal.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
}
|
||||||
|
else if (val is double || val is float || val is decimal)
|
||||||
|
{
|
||||||
|
cell.SetCellValue(Convert.ToDouble(val));
|
||||||
|
}
|
||||||
|
else if (val is int || val is long || val is short)
|
||||||
|
{
|
||||||
|
cell.SetCellValue(Convert.ToDouble(val));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cell.SetCellValue(val.ToString());
|
||||||
|
}
|
||||||
|
cell.CellStyle = dataStyle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 6. 自动调整列宽(限制最大宽度避免过宽) ──
|
||||||
|
for (int c = 0; c < columnCount; c++)
|
||||||
|
{
|
||||||
|
sheet.AutoSizeColumn(c);
|
||||||
|
int colWidth = sheet.GetColumnWidth(c);
|
||||||
|
// 最大列宽限制为 50 个字符宽度 (50 * 256)
|
||||||
|
if (colWidth > 50 * 256)
|
||||||
|
sheet.SetColumnWidth(c, 50 * 256);
|
||||||
|
// 最小列宽
|
||||||
|
else if (colWidth < 10 * 256)
|
||||||
|
sheet.SetColumnWidth(c, 10 * 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 7. 写入文件(使用 FileMode.Create 确保覆盖写入) ──
|
||||||
|
using (FileStream fs = new FileStream(Outpath, FileMode.Create, FileAccess.Write))
|
||||||
|
{
|
||||||
|
workbook.Write(fs);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[ExeclHelper] 导出Excel失败: {ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (workbook != null)
|
||||||
|
{
|
||||||
|
workbook.Close();
|
||||||
|
workbook = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取Execl数据到DataTable(DataSet)中
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filePath">指定Execl文件路径</param>
|
||||||
|
/// <param name="isFirstLineColumnName">设置第一行是否是列名</param>
|
||||||
|
/// <returns>返回一个DataTable数据集</returns>
|
||||||
|
public static DataSet ExcelToDataSet(string filePath, bool isFirstLineColumnName)
|
||||||
|
{
|
||||||
|
DataSet dataSet = new DataSet();
|
||||||
|
int startRow = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||||
|
{
|
||||||
|
IWorkbook workbook = null;
|
||||||
|
// 如果是2007+的Excel版本
|
||||||
|
if (filePath.IndexOf(".xlsx") > 0)
|
||||||
|
{
|
||||||
|
workbook = new XSSFWorkbook(fs);
|
||||||
|
}
|
||||||
|
// 如果是2003-的Excel版本
|
||||||
|
else if (filePath.IndexOf(".xls") > 0)
|
||||||
|
{
|
||||||
|
workbook = new HSSFWorkbook(fs);
|
||||||
|
}
|
||||||
|
if (workbook != null)
|
||||||
|
{
|
||||||
|
//循环读取Excel的每个sheet,每个sheet页都转换为一个DataTable,并放在DataSet中
|
||||||
|
for (int p = 0; p < workbook.NumberOfSheets; p++)
|
||||||
|
{
|
||||||
|
ISheet sheet = workbook.GetSheetAt(p);
|
||||||
|
DataTable dataTable = new DataTable();
|
||||||
|
dataTable.TableName = sheet.SheetName;
|
||||||
|
if (sheet != null)
|
||||||
|
{
|
||||||
|
int rowCount = sheet.LastRowNum;//获取总行数
|
||||||
|
if (rowCount > 0)
|
||||||
|
{
|
||||||
|
IRow firstRow = sheet.GetRow(0);//获取第一行
|
||||||
|
int cellCount = firstRow.LastCellNum;//获取总列数
|
||||||
|
|
||||||
|
//构建datatable的列
|
||||||
|
if (isFirstLineColumnName)
|
||||||
|
{
|
||||||
|
startRow = 1;//如果第一行是列名,则从第二行开始读取
|
||||||
|
for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
|
||||||
|
{
|
||||||
|
ICell cell = firstRow.GetCell(i);
|
||||||
|
if (cell != null)
|
||||||
|
{
|
||||||
|
if (cell.StringCellValue != null)
|
||||||
|
{
|
||||||
|
DataColumn column = new DataColumn(cell.StringCellValue);
|
||||||
|
dataTable.Columns.Add(column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
|
||||||
|
{
|
||||||
|
DataColumn column = new DataColumn("column" + (i + 1));
|
||||||
|
dataTable.Columns.Add(column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//填充行
|
||||||
|
for (int i = startRow; i <= rowCount; ++i)
|
||||||
|
{
|
||||||
|
IRow row = sheet.GetRow(i);
|
||||||
|
if (row == null) continue;
|
||||||
|
|
||||||
|
DataRow dataRow = dataTable.NewRow();
|
||||||
|
for (int j = row.FirstCellNum; j < cellCount; ++j)
|
||||||
|
{
|
||||||
|
ICell cell = row.GetCell(j);
|
||||||
|
if (cell == null)
|
||||||
|
{
|
||||||
|
dataRow[j] = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//CellType(Unknown = -1,Numeric = 0,String = 1,Formula = 2,Blank = 3,Boolean = 4,Error = 5,)
|
||||||
|
switch (cell.CellType)
|
||||||
|
{
|
||||||
|
case CellType.Blank:
|
||||||
|
dataRow[j] = "";
|
||||||
|
break;
|
||||||
|
case CellType.Numeric:
|
||||||
|
short format = cell.CellStyle.DataFormat;
|
||||||
|
//对时间格式(2015.12.5、2015/12/5、2015-12-5等)的处理
|
||||||
|
if (format == 14 || format == 31 || format == 57 || format == 58)
|
||||||
|
dataRow[j] = cell.DateCellValue;
|
||||||
|
else
|
||||||
|
dataRow[j] = cell.NumericCellValue;
|
||||||
|
break;
|
||||||
|
case CellType.String:
|
||||||
|
dataRow[j] = cell.StringCellValue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataTable.Rows.Add(dataRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataSet.Tables.Add(dataTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dataSet;
|
||||||
|
}
|
||||||
|
catch (Exception err)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将DataTable(DataSet)导出到Execl文档
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataSet">传入一个DataSet</param>
|
||||||
|
/// <param name="Outpath">导出路径(可以不加扩展名,不加默认为.xls)</param>
|
||||||
|
/// <returns>返回一个Bool类型的值,表示是否导出成功</returns>
|
||||||
|
/// True表示导出成功,Flase表示导出失败
|
||||||
|
public static bool DataSetToExcel(DataSet dataSet, string Outpath)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (dataSet == null || dataSet.Tables == null || dataSet.Tables.Count == 0 || string.IsNullOrEmpty(Outpath))
|
||||||
|
throw new Exception("输入的DataSet或路径异常");
|
||||||
|
int sheetIndex = 0;
|
||||||
|
//根据输出路径的扩展名判断workbook的实例类型
|
||||||
|
IWorkbook workbook = null;
|
||||||
|
string pathExtensionName = Outpath.Trim().Substring(Outpath.Length - 5);
|
||||||
|
if (pathExtensionName.Contains(".xlsx"))
|
||||||
|
{
|
||||||
|
workbook = new XSSFWorkbook();
|
||||||
|
}
|
||||||
|
else if (pathExtensionName.Contains(".xls"))
|
||||||
|
{
|
||||||
|
workbook = new HSSFWorkbook();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Outpath = Outpath.Trim() + ".xls";
|
||||||
|
workbook = new HSSFWorkbook();
|
||||||
|
}
|
||||||
|
//将DataSet导出为Excel
|
||||||
|
foreach (DataTable dt in dataSet.Tables)
|
||||||
|
{
|
||||||
|
sheetIndex++;
|
||||||
|
if (dt != null && dt.Rows.Count > 0)
|
||||||
|
{
|
||||||
|
ISheet sheet = workbook.CreateSheet(string.IsNullOrEmpty(dt.TableName) ? ("sheet" + sheetIndex) : dt.TableName);//创建一个名称为Sheet0的表
|
||||||
|
int rowCount = dt.Rows.Count;//行数
|
||||||
|
int columnCount = dt.Columns.Count;//列数
|
||||||
|
|
||||||
|
//设置列头
|
||||||
|
IRow row = sheet.CreateRow(0);//excel第一行设为列头
|
||||||
|
for (int c = 0; c < columnCount; c++)
|
||||||
|
{
|
||||||
|
ICell cell = row.CreateCell(c);
|
||||||
|
cell.SetCellValue(dt.Columns[c].ColumnName);
|
||||||
|
}
|
||||||
|
|
||||||
|
//设置每行每列的单元格,
|
||||||
|
for (int i = 0; i < rowCount; i++)
|
||||||
|
{
|
||||||
|
row = sheet.CreateRow(i + 1);
|
||||||
|
for (int j = 0; j < columnCount; j++)
|
||||||
|
{
|
||||||
|
ICell cell = row.CreateCell(j);//excel第二行开始写入数据
|
||||||
|
cell.SetCellValue(dt.Rows[i][j].ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//向outPath输出数据
|
||||||
|
using (FileStream fs = File.OpenWrite(Outpath))
|
||||||
|
{
|
||||||
|
workbook.Write(fs);//向打开的这个xls文件中写入数据
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
25
SCADA/Core/PLC_R.cs
Normal file
25
SCADA/Core/PLC_R.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace DC_A95
|
||||||
|
{
|
||||||
|
public class PLC_R
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 清理PLC字符串乱码(统一入口,支持object参数)
|
||||||
|
/// 过滤不可见字符,保留可打印ASCII和中文等有效字符
|
||||||
|
/// </summary>
|
||||||
|
public static string GetString_CleanGarbled(object input)
|
||||||
|
{
|
||||||
|
if (input == null) return "";
|
||||||
|
string str = input.ToString();
|
||||||
|
if (string.IsNullOrEmpty(str)) return "";
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
foreach (char c in str)
|
||||||
|
{
|
||||||
|
if (c >= 0x20 && c < 0xFFFE) sb.Append(c);
|
||||||
|
}
|
||||||
|
return sb.ToString().Trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
72
SCADA/Core/SqlOperation.cs
Normal file
72
SCADA/Core/SqlOperation.cs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
using MesWork;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace MesWork
|
||||||
|
{
|
||||||
|
public class SqlOperation
|
||||||
|
{
|
||||||
|
public static bool ExecuteStoredProcedure(string name, SqlParameter[] sqlParameters, out string errorMessage)
|
||||||
|
{
|
||||||
|
return DataLinkMesWork.SQLCommon.ExecuteStoredProcedure(name, MesWorkForm.ConnectionString, ref sqlParameters, out errorMessage);
|
||||||
|
}
|
||||||
|
public static bool ExecuteStoredProcedure(string name, SqlParameter[] sqlParameters, out DataTable dt, out string errorMessage)
|
||||||
|
{
|
||||||
|
return DataLinkMesWork.SQLCommon.ExecuteStoredProcedure(name, MesWorkForm.ConnectionString, ref sqlParameters, out dt, out errorMessage);
|
||||||
|
}
|
||||||
|
public static bool ExecuteStoredProcedure(string name, SqlParameter[] sqlParameters, out DataSet ds, out string errorMessage)
|
||||||
|
{
|
||||||
|
return DataLinkMesWork.SQLCommon.ExecuteStoredProcedure(name, MesWorkForm.ConnectionString, ref sqlParameters, out ds, out errorMessage);
|
||||||
|
}
|
||||||
|
public static bool ExecuteSql(string sql, out DataTable dt, out string errorMessage)
|
||||||
|
{
|
||||||
|
return DataLinkMesWork.SQLCommon.ExecuteSql(sql, MesWorkForm.ConnectionString, out dt, out errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ExecuteSql(string sql, out DataSet ds, out string errorMessage)
|
||||||
|
{
|
||||||
|
return DataLinkMesWork.SQLCommon.ExecuteDataset(sql, MesWorkForm.ConnectionString, out ds, out errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ExecuteSql(string sql, out string errorMessage)
|
||||||
|
{
|
||||||
|
return DataLinkMesWork.SQLCommon.ExecuteSql(sql, MesWorkForm.ConnectionString, out errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过SqlBulkCopy复制table数据到数据库
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataset"></param>
|
||||||
|
public static bool SqlbulkcopyInsert(DataTable dt, out string ErrMsg)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
ErrMsg = "";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// SqlBulkCopy sqlbulkcopy = new SqlBulkCopy(connectString, SqlBulkCopyOptions.KeepIdentity);//删除自增ID插入原始数据
|
||||||
|
SqlBulkCopy sqlbulkcopy = new SqlBulkCopy(MesWorkForm.ConnectionString, SqlBulkCopyOptions.UseInternalTransaction);//批量事务处理
|
||||||
|
sqlbulkcopy.DestinationTableName = dt.TableName;//数据库中的表名
|
||||||
|
for (int i = 0; i < dt.Columns.Count; i++)
|
||||||
|
{
|
||||||
|
var columnName = dt.Columns[i].ColumnName.ToString();
|
||||||
|
sqlbulkcopy.ColumnMappings.Add(columnName, columnName);
|
||||||
|
}
|
||||||
|
sqlbulkcopy.WriteToServer(dt);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
catch (Exception err)
|
||||||
|
{
|
||||||
|
ErrMsg = err.Message;
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
192
SCADA/Frm_Login.Designer.cs
generated
Normal file
192
SCADA/Frm_Login.Designer.cs
generated
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
namespace MesWork
|
||||||
|
{
|
||||||
|
partial class Frm_Login
|
||||||
|
{
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.pnl_Card = new System.Windows.Forms.Panel();
|
||||||
|
this.lbl_Title = new System.Windows.Forms.Label();
|
||||||
|
this.lbl_SubTitle = new System.Windows.Forms.Label();
|
||||||
|
this.lbl_User = new System.Windows.Forms.Label();
|
||||||
|
this.txt_LoginID = new System.Windows.Forms.TextBox();
|
||||||
|
this.lbl_Pwd = new System.Windows.Forms.Label();
|
||||||
|
this.txt_userPassword = new System.Windows.Forms.TextBox();
|
||||||
|
this.btn_Login = new System.Windows.Forms.Button();
|
||||||
|
this.btn_Cancel = new System.Windows.Forms.Button();
|
||||||
|
this.lbl_Msg = new System.Windows.Forms.Label();
|
||||||
|
this.pnl_Card.SuspendLayout();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// pnl_Card - 白色登录卡片
|
||||||
|
//
|
||||||
|
this.pnl_Card.BackColor = System.Drawing.Color.White;
|
||||||
|
this.pnl_Card.Location = new System.Drawing.Point(310, 180);
|
||||||
|
this.pnl_Card.Name = "pnl_Card";
|
||||||
|
this.pnl_Card.Size = new System.Drawing.Size(400, 380);
|
||||||
|
this.pnl_Card.TabIndex = 0;
|
||||||
|
this.pnl_Card.Paint += new System.Windows.Forms.PaintEventHandler(this.pnl_Card_Paint);
|
||||||
|
//
|
||||||
|
// lbl_Title - 系统图标+名称
|
||||||
|
//
|
||||||
|
this.lbl_Title.Font = new System.Drawing.Font("微软雅黑", 20F, System.Drawing.FontStyle.Bold);
|
||||||
|
this.lbl_Title.ForeColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.lbl_Title.Location = new System.Drawing.Point(20, 30);
|
||||||
|
this.lbl_Title.Name = "lbl_Title";
|
||||||
|
this.lbl_Title.Size = new System.Drawing.Size(360, 40);
|
||||||
|
this.lbl_Title.TabIndex = 0;
|
||||||
|
this.lbl_Title.Text = "⚖ 称重数据采集分析";
|
||||||
|
this.lbl_Title.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
//
|
||||||
|
// lbl_SubTitle
|
||||||
|
//
|
||||||
|
this.lbl_SubTitle.Font = new System.Drawing.Font("微软雅黑", 11F);
|
||||||
|
this.lbl_SubTitle.ForeColor = System.Drawing.Color.FromArgb(107, 114, 128);
|
||||||
|
this.lbl_SubTitle.Location = new System.Drawing.Point(20, 72);
|
||||||
|
this.lbl_SubTitle.Name = "lbl_SubTitle";
|
||||||
|
this.lbl_SubTitle.Size = new System.Drawing.Size(360, 24);
|
||||||
|
this.lbl_SubTitle.TabIndex = 1;
|
||||||
|
this.lbl_SubTitle.Text = "管理系统";
|
||||||
|
this.lbl_SubTitle.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
//
|
||||||
|
// lbl_User
|
||||||
|
//
|
||||||
|
this.lbl_User.Font = new System.Drawing.Font("微软雅黑", 10F);
|
||||||
|
this.lbl_User.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
|
||||||
|
this.lbl_User.Location = new System.Drawing.Point(40, 120);
|
||||||
|
this.lbl_User.Name = "lbl_User";
|
||||||
|
this.lbl_User.Size = new System.Drawing.Size(60, 24);
|
||||||
|
this.lbl_User.TabIndex = 2;
|
||||||
|
this.lbl_User.Text = "👤 用户名";
|
||||||
|
//
|
||||||
|
// txt_LoginID
|
||||||
|
//
|
||||||
|
this.txt_LoginID.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||||
|
this.txt_LoginID.Font = new System.Drawing.Font("微软雅黑", 12F);
|
||||||
|
this.txt_LoginID.Location = new System.Drawing.Point(40, 148);
|
||||||
|
this.txt_LoginID.Name = "txt_LoginID";
|
||||||
|
this.txt_LoginID.Size = new System.Drawing.Size(320, 29);
|
||||||
|
this.txt_LoginID.TabIndex = 1;
|
||||||
|
this.txt_LoginID.Text = "admin";
|
||||||
|
this.txt_LoginID.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txt_LoginID_KeyDown);
|
||||||
|
//
|
||||||
|
// lbl_Pwd
|
||||||
|
//
|
||||||
|
this.lbl_Pwd.Font = new System.Drawing.Font("微软雅黑", 10F);
|
||||||
|
this.lbl_Pwd.ForeColor = System.Drawing.Color.FromArgb(55, 65, 81);
|
||||||
|
this.lbl_Pwd.Location = new System.Drawing.Point(40, 195);
|
||||||
|
this.lbl_Pwd.Name = "lbl_Pwd";
|
||||||
|
this.lbl_Pwd.Size = new System.Drawing.Size(60, 24);
|
||||||
|
this.lbl_Pwd.TabIndex = 4;
|
||||||
|
this.lbl_Pwd.Text = "🔒 密码";
|
||||||
|
//
|
||||||
|
// txt_userPassword
|
||||||
|
//
|
||||||
|
this.txt_userPassword.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||||
|
this.txt_userPassword.Font = new System.Drawing.Font("微软雅黑", 12F);
|
||||||
|
this.txt_userPassword.Location = new System.Drawing.Point(40, 223);
|
||||||
|
this.txt_userPassword.Name = "txt_userPassword";
|
||||||
|
this.txt_userPassword.PasswordChar = '*';
|
||||||
|
this.txt_userPassword.Size = new System.Drawing.Size(320, 29);
|
||||||
|
this.txt_userPassword.TabIndex = 2;
|
||||||
|
this.txt_userPassword.Text = "admin";
|
||||||
|
this.txt_userPassword.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txt_userPassword_KeyDown);
|
||||||
|
//
|
||||||
|
// btn_Login - Steel Blue 主按钮
|
||||||
|
//
|
||||||
|
this.btn_Login.BackColor = System.Drawing.Color.FromArgb(74, 144, 217);
|
||||||
|
this.btn_Login.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.btn_Login.FlatAppearance.BorderSize = 0;
|
||||||
|
this.btn_Login.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
this.btn_Login.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold);
|
||||||
|
this.btn_Login.ForeColor = System.Drawing.Color.White;
|
||||||
|
this.btn_Login.Location = new System.Drawing.Point(40, 280);
|
||||||
|
this.btn_Login.Name = "btn_Login";
|
||||||
|
this.btn_Login.Size = new System.Drawing.Size(150, 42);
|
||||||
|
this.btn_Login.TabIndex = 3;
|
||||||
|
this.btn_Login.Text = "登 录";
|
||||||
|
this.btn_Login.UseVisualStyleBackColor = false;
|
||||||
|
this.btn_Login.Click += new System.EventHandler(this.btn_Login_Click);
|
||||||
|
//
|
||||||
|
// btn_Cancel - 灰色边框按钮
|
||||||
|
//
|
||||||
|
this.btn_Cancel.BackColor = System.Drawing.Color.White;
|
||||||
|
this.btn_Cancel.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.btn_Cancel.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(209, 213, 219);
|
||||||
|
this.btn_Cancel.FlatAppearance.BorderSize = 1;
|
||||||
|
this.btn_Cancel.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
|
this.btn_Cancel.Font = new System.Drawing.Font("微软雅黑", 12F);
|
||||||
|
this.btn_Cancel.ForeColor = System.Drawing.Color.FromArgb(107, 114, 128);
|
||||||
|
this.btn_Cancel.Location = new System.Drawing.Point(210, 280);
|
||||||
|
this.btn_Cancel.Name = "btn_Cancel";
|
||||||
|
this.btn_Cancel.Size = new System.Drawing.Size(150, 42);
|
||||||
|
this.btn_Cancel.TabIndex = 4;
|
||||||
|
this.btn_Cancel.Text = "取 消";
|
||||||
|
this.btn_Cancel.UseVisualStyleBackColor = false;
|
||||||
|
this.btn_Cancel.Click += new System.EventHandler(this.btn_Cancel_Click);
|
||||||
|
//
|
||||||
|
// lbl_Msg
|
||||||
|
//
|
||||||
|
this.lbl_Msg.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||||
|
this.lbl_Msg.ForeColor = System.Drawing.Color.FromArgb(239, 68, 68);
|
||||||
|
this.lbl_Msg.Location = new System.Drawing.Point(40, 332);
|
||||||
|
this.lbl_Msg.Name = "lbl_Msg";
|
||||||
|
this.lbl_Msg.Size = new System.Drawing.Size(320, 24);
|
||||||
|
this.lbl_Msg.TabIndex = 8;
|
||||||
|
this.lbl_Msg.Visible = false;
|
||||||
|
//
|
||||||
|
// 添加控件到卡片
|
||||||
|
//
|
||||||
|
this.pnl_Card.Controls.Add(this.lbl_Title);
|
||||||
|
this.pnl_Card.Controls.Add(this.lbl_SubTitle);
|
||||||
|
this.pnl_Card.Controls.Add(this.lbl_User);
|
||||||
|
this.pnl_Card.Controls.Add(this.txt_LoginID);
|
||||||
|
this.pnl_Card.Controls.Add(this.lbl_Pwd);
|
||||||
|
this.pnl_Card.Controls.Add(this.txt_userPassword);
|
||||||
|
this.pnl_Card.Controls.Add(this.btn_Login);
|
||||||
|
this.pnl_Card.Controls.Add(this.btn_Cancel);
|
||||||
|
this.pnl_Card.Controls.Add(this.lbl_Msg);
|
||||||
|
//
|
||||||
|
// Frm_Login
|
||||||
|
//
|
||||||
|
this.AcceptButton = this.btn_Login;
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||||
|
this.BackColor = System.Drawing.Color.FromArgb(240, 244, 248);
|
||||||
|
this.ClientSize = new System.Drawing.Size(1024, 720);
|
||||||
|
this.Controls.Add(this.pnl_Card);
|
||||||
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
|
||||||
|
this.Name = "Frm_Login";
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||||
|
this.Text = "称重数据采集分析管理系统 - 登录";
|
||||||
|
this.pnl_Card.ResumeLayout(false);
|
||||||
|
this.pnl_Card.PerformLayout();
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.Panel pnl_Card;
|
||||||
|
private System.Windows.Forms.Label lbl_Title;
|
||||||
|
private System.Windows.Forms.Label lbl_SubTitle;
|
||||||
|
private System.Windows.Forms.Label lbl_User;
|
||||||
|
private System.Windows.Forms.TextBox txt_LoginID;
|
||||||
|
private System.Windows.Forms.Label lbl_Pwd;
|
||||||
|
private System.Windows.Forms.TextBox txt_userPassword;
|
||||||
|
private System.Windows.Forms.Button btn_Login;
|
||||||
|
private System.Windows.Forms.Button btn_Cancel;
|
||||||
|
private System.Windows.Forms.Label lbl_Msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
219
SCADA/Frm_Login.cs
Normal file
219
SCADA/Frm_Login.cs
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.IO;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace MesWork
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 登录页面 — 全屏背景图 + 右侧白色登录卡片
|
||||||
|
/// </summary>
|
||||||
|
public partial class Frm_Login : Form
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 背景图片缓存
|
||||||
|
/// </summary>
|
||||||
|
private Image _bgImage;
|
||||||
|
|
||||||
|
public Frm_Login()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
DoubleBuffered = true;
|
||||||
|
LoadBackgroundImage();
|
||||||
|
LoadIcon();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载任务栏图标
|
||||||
|
/// </summary>
|
||||||
|
private void LoadIcon()
|
||||||
|
{
|
||||||
|
IconHelper.ApplyIcon(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载背景图片(从 Resources 目录)
|
||||||
|
/// </summary>
|
||||||
|
private void LoadBackgroundImage()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string bgPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources", "login_bg.png");
|
||||||
|
if (File.Exists(bgPath))
|
||||||
|
_bgImage = Image.FromFile(bgPath);
|
||||||
|
}
|
||||||
|
catch { /* 图片加载失败时使用渐变背景兜底 */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 绘制背景:优先使用背景图,否则渐变兜底
|
||||||
|
/// </summary>
|
||||||
|
protected override void OnPaint(PaintEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnPaint(e);
|
||||||
|
var g = e.Graphics;
|
||||||
|
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||||
|
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||||
|
|
||||||
|
if (_bgImage != null)
|
||||||
|
{
|
||||||
|
// 全屏铺满背景图
|
||||||
|
g.DrawImage(_bgImage, 0, 0, ClientSize.Width, ClientSize.Height);
|
||||||
|
|
||||||
|
// 右侧半透明白色蒙层(让登录卡片区域更清晰)
|
||||||
|
using (var overlay = new SolidBrush(Color.FromArgb(180, 255, 255, 255)))
|
||||||
|
{
|
||||||
|
g.FillRectangle(overlay, ClientSize.Width / 2, 0, ClientSize.Width / 2, ClientSize.Height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 渐变兜底
|
||||||
|
using (var brush = new LinearGradientBrush(
|
||||||
|
ClientRectangle,
|
||||||
|
Color.FromArgb(30, 58, 95),
|
||||||
|
Color.FromArgb(240, 244, 248),
|
||||||
|
LinearGradientMode.Horizontal))
|
||||||
|
{
|
||||||
|
g.FillRectangle(brush, ClientRectangle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 底部版本信息(放在右下角白色区域,确保清晰可读)
|
||||||
|
using (var font = new Font("微软雅黑", 9F))
|
||||||
|
using (var brush = new SolidBrush(Color.FromArgb(160, 120, 120, 120)))
|
||||||
|
{
|
||||||
|
string ver = "v1.0.0 | 潍柴动力 · 称重数据采集分析管理系统";
|
||||||
|
var sz = g.MeasureString(ver, font);
|
||||||
|
g.DrawString(ver, font, brush, ClientSize.Width - sz.Width - 20, ClientSize.Height - 36);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 窗口大小变化时重新定位登录卡片到右半区中央
|
||||||
|
/// </summary>
|
||||||
|
protected override void OnResize(EventArgs e)
|
||||||
|
{
|
||||||
|
base.OnResize(e);
|
||||||
|
if (pnl_Card != null)
|
||||||
|
{
|
||||||
|
// 卡片放在右半区的中心位置
|
||||||
|
int rightHalfCenter = ClientSize.Width / 2 + ClientSize.Width / 4;
|
||||||
|
pnl_Card.Location = new Point(
|
||||||
|
rightHalfCenter - pnl_Card.Width / 2,
|
||||||
|
(ClientSize.Height - pnl_Card.Height) / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 卡片圆角绘制
|
||||||
|
/// </summary>
|
||||||
|
private void pnl_Card_Paint(object sender, PaintEventArgs e)
|
||||||
|
{
|
||||||
|
var panel = (Panel)sender;
|
||||||
|
int radius = 12;
|
||||||
|
var rect = new Rectangle(0, 0, panel.Width - 1, panel.Height - 1);
|
||||||
|
using (var path = new GraphicsPath())
|
||||||
|
{
|
||||||
|
path.AddArc(rect.X, rect.Y, radius * 2, radius * 2, 180, 90);
|
||||||
|
path.AddArc(rect.Right - radius * 2, rect.Y, radius * 2, radius * 2, 270, 90);
|
||||||
|
path.AddArc(rect.Right - radius * 2, rect.Bottom - radius * 2, radius * 2, radius * 2, 0, 90);
|
||||||
|
path.AddArc(rect.X, rect.Bottom - radius * 2, radius * 2, radius * 2, 90, 90);
|
||||||
|
path.CloseFigure();
|
||||||
|
panel.Region = new Region(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// 登录逻辑
|
||||||
|
// ====================================================================
|
||||||
|
|
||||||
|
private void btn_Cancel_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (MesWorkForm.Curr_UserName == "") Application.Exit();
|
||||||
|
else DialogResult = DialogResult.Cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btn_Login_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (txt_LoginID.Text.Trim() == "")
|
||||||
|
{
|
||||||
|
lbl_Msg.Text = "⚠ 用户名不能为空";
|
||||||
|
lbl_Msg.Visible = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用新的用户管理表登录验证
|
||||||
|
var res = User_Login(txt_LoginID.Text.Trim(), txt_userPassword.Text, out string name, out string perm);
|
||||||
|
if (res)
|
||||||
|
{
|
||||||
|
MesWorkForm.Curr_LoginID = txt_LoginID.Text.Trim();
|
||||||
|
MesWorkForm.Curr_UserPassWord = txt_userPassword.Text;
|
||||||
|
MesWorkForm.Curr_UserName = name;
|
||||||
|
|
||||||
|
// 记录登录日志
|
||||||
|
try { B_DB_Opera.SaveLog_Request(MesWorkForm.Curr_Station, Log_Type.ZK_Login, "", Log_FromAndTo.ZK, Log_FromAndTo.ZK, $"用户[{name}({txt_LoginID.Text.Trim()})]登录系统", out long _); } catch { }
|
||||||
|
|
||||||
|
DialogResult = DialogResult.OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lbl_Msg.Text = "⚠ 登录失败,请检查用户名和密码";
|
||||||
|
lbl_Msg.Visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 调用 用户管理_登录验证 SP
|
||||||
|
/// </summary>
|
||||||
|
private bool User_Login(string userName, string pwd, out string name, out string permission)
|
||||||
|
{
|
||||||
|
name = "";
|
||||||
|
permission = "";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var sp = "用户管理_登录验证";
|
||||||
|
var parms = new System.Data.SqlClient.SqlParameter[]
|
||||||
|
{
|
||||||
|
new System.Data.SqlClient.SqlParameter("@用户名", userName),
|
||||||
|
new System.Data.SqlClient.SqlParameter("@密码", pwd)
|
||||||
|
};
|
||||||
|
SqlOperation.ExecuteStoredProcedure(sp, parms, out System.Data.DataTable dt, out string err);
|
||||||
|
if (dt != null && dt.Rows.Count > 0)
|
||||||
|
{
|
||||||
|
name = dt.Rows[0]["姓名"].ToString();
|
||||||
|
permission = dt.Rows[0]["权限"].ToString();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MesWorkForm.WriteLog_Info("Login", $"登录异常:{ex.Message}", ex);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 回车切换焦点:用户名 → 密码
|
||||||
|
/// </summary>
|
||||||
|
private void txt_LoginID_KeyDown(object sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.KeyCode == Keys.Enter) { txt_userPassword.Focus(); e.SuppressKeyPress = true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 回车触发登录:密码 → 登录
|
||||||
|
/// </summary>
|
||||||
|
private void txt_userPassword_KeyDown(object sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.KeyCode == Keys.Enter) { btn_Login_Click(sender, e); e.SuppressKeyPress = true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnFormClosed(FormClosedEventArgs e)
|
||||||
|
{
|
||||||
|
_bgImage?.Dispose();
|
||||||
|
base.OnFormClosed(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
61
SCADA/Frm_Login.resx
Normal file
61
SCADA/Frm_Login.resx
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?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>
|
||||||
506
SCADA/Funtion/B_DB_Opera.cs
Normal file
506
SCADA/Funtion/B_DB_Opera.cs
Normal file
@@ -0,0 +1,506 @@
|
|||||||
|
using DC_A95;
|
||||||
|
using ExternalDataSync;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MesWork
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 数据库操作
|
||||||
|
/// </summary>
|
||||||
|
public class B_DB_Opera
|
||||||
|
{
|
||||||
|
|
||||||
|
public static void Event_WorkStart(string opName, int tagTypeCodeID, string partType, string tagID)
|
||||||
|
{
|
||||||
|
var ChangeTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
var procedureName = "Event_WorkStart";
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@OpName", opName),
|
||||||
|
new SqlParameter("@TagTypeCodeID", tagTypeCodeID),
|
||||||
|
new SqlParameter("@PartType", partType),
|
||||||
|
new SqlParameter("@ChangeTime",ChangeTime),
|
||||||
|
new SqlParameter("@TagID", tagID)
|
||||||
|
};
|
||||||
|
SqlOperation.ExecuteStoredProcedure(procedureName, sqlParameter, out string errorMessage);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Event_WorkEnd(string opName, int tagTypeCodeID, string partType
|
||||||
|
, string barCode, int qualityMask, int outCount, int duration
|
||||||
|
, string tagID)
|
||||||
|
{
|
||||||
|
var ChangeTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
var procedureName = "Event_WorkEnd";
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@OpName", opName),
|
||||||
|
new SqlParameter("@TagTypeCodeID", tagTypeCodeID),
|
||||||
|
new SqlParameter("@PartType", partType),
|
||||||
|
new SqlParameter("@BarCode", barCode),
|
||||||
|
new SqlParameter("@QualityMask", qualityMask),
|
||||||
|
new SqlParameter("@OutCount", outCount),
|
||||||
|
new SqlParameter("@Duration", duration),
|
||||||
|
new SqlParameter("@ChangeTime",ChangeTime),
|
||||||
|
new SqlParameter("@TagID", tagID)
|
||||||
|
};
|
||||||
|
|
||||||
|
SqlOperation.ExecuteStoredProcedure(procedureName, sqlParameter, out string errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void Event_Signal_Log(string opName, int tagTypeCodeID, string value, string tagID)
|
||||||
|
{
|
||||||
|
var ChangeTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
var procedureName = "Event_Signal_Log";
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@OpName", opName),
|
||||||
|
new SqlParameter("@TagTypeCodeID", tagTypeCodeID),
|
||||||
|
new SqlParameter("@Value", value),
|
||||||
|
new SqlParameter("@ChangeTime",ChangeTime),
|
||||||
|
new SqlParameter("@TagID", tagID)
|
||||||
|
};
|
||||||
|
|
||||||
|
SqlOperation.ExecuteStoredProcedure(procedureName, sqlParameter, out string errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void Event_Alarm_Start(string opName, int tagTypeCodeID, string alarmText, string alarmLevel, string tagID)
|
||||||
|
{
|
||||||
|
var ChangeTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
var procedureName = "Event_Alarm_Start";
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@OpName", opName),
|
||||||
|
new SqlParameter("@TagTypeCodeID", tagTypeCodeID),
|
||||||
|
new SqlParameter("@AlarmText", alarmText),
|
||||||
|
new SqlParameter("@AlarmLevel", alarmLevel),
|
||||||
|
new SqlParameter("@ChangeTime",ChangeTime),
|
||||||
|
new SqlParameter("@TagID", tagID)
|
||||||
|
};
|
||||||
|
|
||||||
|
SqlOperation.ExecuteStoredProcedure(procedureName, sqlParameter, out string errorMessage);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void Event_Alarm_End(string opName, int tagTypeCodeID, string alarmText, string alarmLevel, string tagID)
|
||||||
|
{
|
||||||
|
var ChangeTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
var procedureName = "Event_Alarm_End";
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@OpName", opName),
|
||||||
|
new SqlParameter("@TagTypeCodeID", tagTypeCodeID),
|
||||||
|
new SqlParameter("@AlarmText", alarmText),
|
||||||
|
new SqlParameter("@AlarmLevel", alarmLevel),
|
||||||
|
new SqlParameter("@ChangeTime",ChangeTime),
|
||||||
|
new SqlParameter("@TagID", tagID)
|
||||||
|
};
|
||||||
|
|
||||||
|
SqlOperation.ExecuteStoredProcedure(procedureName, sqlParameter, out string errorMessage);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Event_AlarmAndTip_Start(string opName, int tagTypeCodeID, string alarmText, string tagID, int Alarm1_Tip2)
|
||||||
|
{
|
||||||
|
var ChangeTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
var procedureName = "Event_AlarmAndTip_Start";
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@OpName", opName),
|
||||||
|
new SqlParameter("@TagTypeCodeID", tagTypeCodeID),
|
||||||
|
new SqlParameter("@AlarmText", alarmText),
|
||||||
|
new SqlParameter("@ChangeTime",ChangeTime),
|
||||||
|
new SqlParameter("@TagID", tagID),
|
||||||
|
new SqlParameter("@Alarm1_Tip2", Alarm1_Tip2),
|
||||||
|
};
|
||||||
|
SqlOperation.ExecuteStoredProcedure(procedureName, sqlParameter, out string errorMessage);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void MES_StatusChange(string opName, int StatusCode, string TriggerTime)
|
||||||
|
{
|
||||||
|
var procedureName = "设备管理_状态变化新增";
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@opName", opName),
|
||||||
|
new SqlParameter("@StatusCode", StatusCode),
|
||||||
|
new SqlParameter("@TriggerTime", TriggerTime),
|
||||||
|
};
|
||||||
|
|
||||||
|
SqlOperation.ExecuteStoredProcedure(procedureName, sqlParameter, out string errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void Query_AlarmData(string opName, out int count, out string text)
|
||||||
|
{
|
||||||
|
count = 0;
|
||||||
|
text = "";
|
||||||
|
|
||||||
|
var ChangeTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
var procedureName = "Query_AlarmData";
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@OpName", opName),
|
||||||
|
};
|
||||||
|
SqlOperation.ExecuteStoredProcedure(procedureName, sqlParameter, out DataTable dt, out string errorMessage);
|
||||||
|
if (dt.Rows.Count > 0)
|
||||||
|
{
|
||||||
|
count = Convert.ToInt32(dt.Rows[0]["COUNT"].ToString());
|
||||||
|
text = dt.Rows[0]["TEXT"].ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void Event_DeviceStatus_UseTime(string opName, string Onhours, string Workhours, string DeviceStatus)
|
||||||
|
{
|
||||||
|
var ChangeTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
var procedureName = "Event_DeviceStatus_UseTime";
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@OpName", opName),
|
||||||
|
new SqlParameter("@Onhours", Onhours),
|
||||||
|
new SqlParameter("@Workhours", Workhours),
|
||||||
|
new SqlParameter("@DeviceStatus", DeviceStatus),
|
||||||
|
new SqlParameter("@ChangeTime",ChangeTime),
|
||||||
|
};
|
||||||
|
|
||||||
|
SqlOperation.ExecuteStoredProcedure(procedureName, sqlParameter, out string errorMessage);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Event_DeviceStatus_Change(string opName, string DeviceStatus)
|
||||||
|
{
|
||||||
|
var ChangeTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
var procedureName = "Event_DeviceStatus_Change";
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@OpName", opName),
|
||||||
|
new SqlParameter("@DeviceStatus", DeviceStatus),
|
||||||
|
new SqlParameter("@ChangeTime",ChangeTime),
|
||||||
|
};
|
||||||
|
|
||||||
|
SqlOperation.ExecuteStoredProcedure(procedureName, sqlParameter, out string errorMessage);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 请求日志记录
|
||||||
|
/// </summary>
|
||||||
|
public static void SaveLog_Request(string StationName, Log_Type LogType, string ReqCode, Log_FromAndTo ReqFrom, Log_FromAndTo ReqTo, string ReqStr, out long AID, string ReqStrSafe = "")
|
||||||
|
{
|
||||||
|
AID = -1;
|
||||||
|
var CreateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
ReqStr = PLC_R.GetString_CleanGarbled(ReqStr);
|
||||||
|
|
||||||
|
var param1 = new SqlParameter[] {
|
||||||
|
new SqlParameter("@工位号", StationName),
|
||||||
|
new SqlParameter("@日志类型", LogType.ToString()),
|
||||||
|
new SqlParameter("@TaskID", ReqCode),
|
||||||
|
new SqlParameter("@请求CMD",""),
|
||||||
|
new SqlParameter("@请求FROM",ReqFrom.ToString()),
|
||||||
|
new SqlParameter("@请求TO",ReqTo.ToString()),
|
||||||
|
new SqlParameter("@请求时间",CreateTime),
|
||||||
|
new SqlParameter("@请求内容",ReqStr),
|
||||||
|
new SqlParameter("@请求内容安全",ReqStrSafe)
|
||||||
|
};
|
||||||
|
DataLinkMesWork.SQLCommon.ExecuteStoredProcedure("Event_Log_Request", MesWorkForm.ConnectionString, ref param1, out DataTable dt, out string errorMessage);
|
||||||
|
if (dt.Rows.Count > 0)
|
||||||
|
{
|
||||||
|
AID = Convert.ToInt64(dt.Rows[0]["AID"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 响应日志记录
|
||||||
|
/// </summary>
|
||||||
|
public static void SaveLog_Response(string result, long AID)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var CreateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
var param4 = new SqlParameter[]
|
||||||
|
{
|
||||||
|
new SqlParameter("@AID",AID),
|
||||||
|
new SqlParameter("@响应时间",CreateTime),
|
||||||
|
new SqlParameter("@响应内容",JsonConvert.SerializeObject(result))
|
||||||
|
};
|
||||||
|
DataLinkMesWork.SQLCommon.ExecuteStoredProcedure("Event_Log_Respond", MesWorkForm.ConnectionString, ref param4, out string errorMessage);
|
||||||
|
}
|
||||||
|
catch (Exception err)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// 称重业务数据库方法(调用存储过程,统一 result/msg 返回格式)
|
||||||
|
// ====================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从工件管理表查询机型参数(加油量/抽油量/密度/残油量上下限)
|
||||||
|
/// </summary>
|
||||||
|
public static bool QueryWorkpieceByModel(string modelNo, out decimal addOilQty, out decimal extractOilQty, out decimal density,
|
||||||
|
out decimal residualOilUpperLimit, out decimal residualOilLowerLimit)
|
||||||
|
{
|
||||||
|
addOilQty = 0; extractOilQty = 0; density = 0; residualOilUpperLimit = 0; residualOilLowerLimit = 0;
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@机型号", modelNo)
|
||||||
|
};
|
||||||
|
SqlOperation.ExecuteStoredProcedure("称重_查询工件参数", sqlParameter, out DataTable dt, out string err);
|
||||||
|
if (dt != null && dt.Rows.Count > 0 && dt.Rows[0]["result"].ToString() == "1")
|
||||||
|
{
|
||||||
|
var row = dt.Rows[0];
|
||||||
|
decimal.TryParse(row["加油量"]?.ToString(), out addOilQty);
|
||||||
|
decimal.TryParse(row["抽油量"]?.ToString(), out extractOilQty);
|
||||||
|
decimal.TryParse(row["密度"]?.ToString(), out density);
|
||||||
|
decimal.TryParse(row["残油量上限"]?.ToString(), out residualOilUpperLimit);
|
||||||
|
decimal.TryParse(row["残油量下限"]?.ToString(), out residualOilLowerLimit);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 插入称重记录
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>新记录ID,失败返回-1</returns>
|
||||||
|
public static long InsertWeighingRecord(
|
||||||
|
string stationNo, string weighType, string engineNo, string modelNo,
|
||||||
|
string orderNo, string palletNo,
|
||||||
|
decimal inWeight, decimal outWeight,
|
||||||
|
decimal addOilQty, decimal extractOilQty, decimal density,
|
||||||
|
decimal residualOilUpperLimit, decimal residualOilLowerLimit,
|
||||||
|
decimal oilRelease, decimal residualOil,
|
||||||
|
int qualityFlag, decimal waterContent,
|
||||||
|
string dataSource, string worker, int isComplete)
|
||||||
|
{
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@工位号", stationNo),
|
||||||
|
new SqlParameter("@称重类型", weighType),
|
||||||
|
new SqlParameter("@发动机号", engineNo),
|
||||||
|
new SqlParameter("@机型号", modelNo),
|
||||||
|
new SqlParameter("@工单号", orderNo),
|
||||||
|
new SqlParameter("@托盘号", palletNo),
|
||||||
|
new SqlParameter("@进站重量", inWeight),
|
||||||
|
new SqlParameter("@离站重量", outWeight),
|
||||||
|
new SqlParameter("@加油量", addOilQty),
|
||||||
|
new SqlParameter("@抽油量", extractOilQty),
|
||||||
|
new SqlParameter("@密度", density),
|
||||||
|
new SqlParameter("@残油量上限", residualOilUpperLimit),
|
||||||
|
new SqlParameter("@残油量下限", residualOilLowerLimit),
|
||||||
|
new SqlParameter("@放油量", oilRelease),
|
||||||
|
new SqlParameter("@残油量", residualOil),
|
||||||
|
new SqlParameter("@合格标志", qualityFlag),
|
||||||
|
new SqlParameter("@水含量", waterContent),
|
||||||
|
new SqlParameter("@数据来源", dataSource),
|
||||||
|
new SqlParameter("@操作者", worker),
|
||||||
|
new SqlParameter("@是否完成", isComplete)
|
||||||
|
};
|
||||||
|
SqlOperation.ExecuteStoredProcedure("称重记录_增加", sqlParameter, out DataTable dt, out string err);
|
||||||
|
if (dt != null && dt.Rows.Count > 0 && dt.Rows[0]["result"].ToString() == "1")
|
||||||
|
{
|
||||||
|
return Convert.ToInt64(dt.Rows[0]["ID"]);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查询放油前记录(按发动机号匹配,称重类型='空中'且未完成)
|
||||||
|
/// </summary>
|
||||||
|
public static bool QueryWeighingBeforeOil(string engineNo, out long recordId, out decimal preWeight, out decimal addOilQty, out decimal extractOilQty, out decimal density)
|
||||||
|
{
|
||||||
|
recordId = 0; preWeight = 0; addOilQty = 0; extractOilQty = 0; density = 0;
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@发动机号", engineNo)
|
||||||
|
};
|
||||||
|
SqlOperation.ExecuteStoredProcedure("称重记录_查询放油前", sqlParameter, out DataTable dt, out string err);
|
||||||
|
if (dt != null && dt.Rows.Count > 0 && dt.Rows[0]["result"].ToString() == "1")
|
||||||
|
{
|
||||||
|
var row = dt.Rows[0];
|
||||||
|
recordId = Convert.ToInt64(row["ID"]);
|
||||||
|
decimal.TryParse(row["进站重量"]?.ToString(), out preWeight);
|
||||||
|
decimal.TryParse(row["加油量"]?.ToString(), out addOilQty);
|
||||||
|
decimal.TryParse(row["抽油量"]?.ToString(), out extractOilQty);
|
||||||
|
decimal.TryParse(row["密度"]?.ToString(), out density);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查询指定工位最新的称重记录(不过滤完成状态)
|
||||||
|
/// </summary>
|
||||||
|
public static bool QueryLatestRecord(string stationNo, string engineNo,
|
||||||
|
out long recordId, out decimal preWeight,
|
||||||
|
out decimal addOilQty, out decimal extractOilQty, out decimal density)
|
||||||
|
{
|
||||||
|
recordId = 0; preWeight = 0; addOilQty = 0; extractOilQty = 0; density = 0;
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@工位号", stationNo),
|
||||||
|
new SqlParameter("@发动机号", engineNo)
|
||||||
|
};
|
||||||
|
SqlOperation.ExecuteStoredProcedure("称重记录_查询最新", sqlParameter, out DataTable dt, out string err);
|
||||||
|
if (dt != null && dt.Rows.Count > 0 && dt.Rows[0]["result"].ToString() == "1")
|
||||||
|
{
|
||||||
|
var row = dt.Rows[0];
|
||||||
|
recordId = Convert.ToInt64(row["ID"]);
|
||||||
|
decimal.TryParse(row["进站重量"]?.ToString(), out preWeight);
|
||||||
|
decimal.TryParse(row["加油量"]?.ToString(), out addOilQty);
|
||||||
|
decimal.TryParse(row["抽油量"]?.ToString(), out extractOilQty);
|
||||||
|
decimal.TryParse(row["密度"]?.ToString(), out density);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新称重记录为完成状态(保存称重结果)
|
||||||
|
/// </summary>
|
||||||
|
public static bool UpdateWeighingComplete(long recordId, string weighType, string stationNo,
|
||||||
|
decimal weight, decimal oilRelease, decimal residualOil, decimal waterContent, out int qualityFlag, out string msg)
|
||||||
|
{
|
||||||
|
qualityFlag = 2;
|
||||||
|
msg = "";
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@ID", recordId),
|
||||||
|
new SqlParameter("@称重类型", weighType),
|
||||||
|
new SqlParameter("@工位号", stationNo),
|
||||||
|
new SqlParameter("@称重重量", weight),
|
||||||
|
new SqlParameter("@放油量", oilRelease),
|
||||||
|
new SqlParameter("@残油量", residualOil),
|
||||||
|
new SqlParameter("@水含量", waterContent)
|
||||||
|
};
|
||||||
|
SqlOperation.ExecuteStoredProcedure("称重记录_完成更新", sqlParameter, out DataTable dt, out string err);
|
||||||
|
if (dt == null || dt.Rows.Count == 0)
|
||||||
|
{
|
||||||
|
msg = string.IsNullOrEmpty(err) ? "称重记录完成更新未返回结果" : err;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qualityFlag = Convert.ToInt32(dt.Rows[0]["result"]);
|
||||||
|
msg = dt.Rows[0]["msg"].ToString();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// 过站记录操作方法
|
||||||
|
// ====================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 新增过站记录(case 44 请求工作时调用)
|
||||||
|
/// </summary>
|
||||||
|
public static long InsertStationRecord(string engineNo, string modelNo, string orderNo, string palletNo,
|
||||||
|
string stationNo, string stationName, decimal addOilQty, decimal extractOilQty, decimal density, string worker)
|
||||||
|
{
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@发动机号", engineNo),
|
||||||
|
new SqlParameter("@机型号", modelNo),
|
||||||
|
new SqlParameter("@工单号", orderNo),
|
||||||
|
new SqlParameter("@托盘号", palletNo),
|
||||||
|
new SqlParameter("@工位号", stationNo),
|
||||||
|
new SqlParameter("@工位名称", stationName),
|
||||||
|
new SqlParameter("@加油量", addOilQty),
|
||||||
|
new SqlParameter("@抽油量", extractOilQty),
|
||||||
|
new SqlParameter("@油密度", density),
|
||||||
|
new SqlParameter("@操作者", worker)
|
||||||
|
};
|
||||||
|
SqlOperation.ExecuteStoredProcedure("过站记录_新增", sqlParameter, out DataTable dt, out string err);
|
||||||
|
if (dt != null && dt.Rows.Count > 0 && dt.Rows[0]["result"].ToString() == "1")
|
||||||
|
return Convert.ToInt64(dt.Rows[0]["ID"]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新过站记录为完成(case 19 请求保存时调用)
|
||||||
|
/// </summary>
|
||||||
|
public static bool UpdateStationComplete(string engineNo, string stationNo, decimal weight)
|
||||||
|
{
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@发动机号", engineNo),
|
||||||
|
new SqlParameter("@工位号", stationNo),
|
||||||
|
new SqlParameter("@称重重量", weight)
|
||||||
|
};
|
||||||
|
SqlOperation.ExecuteStoredProcedure("过站记录_完成", sqlParameter, out DataTable dt, out string err);
|
||||||
|
return dt != null && dt.Rows.Count > 0 && dt.Rows[0]["result"].ToString() == "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// 称重曲线数据操作方法
|
||||||
|
// ====================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建曲线段记录(工件到位时调用)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>段ID,失败返回-1</returns>
|
||||||
|
public static long Curve_StartSegment(string opName, string engineNo, string modelNo)
|
||||||
|
{
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@工位号", opName),
|
||||||
|
new SqlParameter("@发动机号", engineNo),
|
||||||
|
new SqlParameter("@机型号", modelNo ?? (object)DBNull.Value)
|
||||||
|
};
|
||||||
|
SqlOperation.ExecuteStoredProcedure("称重曲线_开始段", sqlParameter, out DataTable dt, out string err);
|
||||||
|
if (dt != null && dt.Rows.Count > 0 && dt.Rows[0]["result"].ToString() == "1")
|
||||||
|
{
|
||||||
|
return Convert.ToInt64(dt.Rows[0]["ID"]);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量写入曲线采样点(采集线程每攒够N条调用一次)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="segmentId">段ID</param>
|
||||||
|
/// <param name="points">采样点列表</param>
|
||||||
|
/// <returns>写入条数,失败返回0</returns>
|
||||||
|
public static int Curve_WritePoints(long segmentId, List<CurveSamplePoint> points)
|
||||||
|
{
|
||||||
|
if (points == null || points.Count == 0) return 0;
|
||||||
|
|
||||||
|
// 用 JSON 序列化避免小数区域格式和字符串拼接转义问题。
|
||||||
|
var json = JsonConvert.SerializeObject(points.Select(p => new
|
||||||
|
{
|
||||||
|
seq = p.SeqNo,
|
||||||
|
time = p.SampleTime.ToString("yyyy-MM-ddTHH:mm:ss.fff"),
|
||||||
|
weight = p.Weight
|
||||||
|
}));
|
||||||
|
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@段ID", segmentId),
|
||||||
|
new SqlParameter("@采样数据", json)
|
||||||
|
};
|
||||||
|
SqlOperation.ExecuteStoredProcedure("称重曲线_批量写入", sqlParameter, out DataTable dt, out string err);
|
||||||
|
if (dt != null && dt.Rows.Count > 0 && dt.Rows[0]["result"].ToString() == "1")
|
||||||
|
{
|
||||||
|
return Convert.ToInt32(dt.Rows[0]["count"]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 结束曲线段(请求保存时调用,关联称重记录ID)
|
||||||
|
/// </summary>
|
||||||
|
public static bool Curve_EndSegment(long segmentId, long weighingRecordId)
|
||||||
|
{
|
||||||
|
var sqlParameter = new SqlParameter[] {
|
||||||
|
new SqlParameter("@段ID", segmentId),
|
||||||
|
new SqlParameter("@称重记录ID", weighingRecordId > 0 ? (object)weighingRecordId : DBNull.Value)
|
||||||
|
};
|
||||||
|
SqlOperation.ExecuteStoredProcedure("称重曲线_结束段", sqlParameter, out DataTable dt, out string err);
|
||||||
|
return dt != null && dt.Rows.Count > 0 && dt.Rows[0]["result"].ToString() == "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 曲线采样点数据结构
|
||||||
|
/// </summary>
|
||||||
|
public class CurveSamplePoint
|
||||||
|
{
|
||||||
|
public int SeqNo;
|
||||||
|
public DateTime SampleTime;
|
||||||
|
public decimal Weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
40
SCADA/Funtion/MIS_Device.cs
Normal file
40
SCADA/Funtion/MIS_Device.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using DC_A95;
|
||||||
|
using OpcBasic;
|
||||||
|
using OpcData;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Data.SqlClient;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using SystemFramework;
|
||||||
|
|
||||||
|
namespace MesWork
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 设备状态的处理
|
||||||
|
/// </summary>
|
||||||
|
public partial class MesWorkForm
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设备状态的处理
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void MIS_Device(object e)
|
||||||
|
{
|
||||||
|
var eState = (DeviceDriver_BasicData.PlcStateEvetnArgs)e;
|
||||||
|
var ip = eState.IP.ToString();
|
||||||
|
var onLine = eState.OnLine;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
509
SCADA/Funtion/MIS_Funtion.cs
Normal file
509
SCADA/Funtion/MIS_Funtion.cs
Normal file
@@ -0,0 +1,509 @@
|
|||||||
|
using ExternalDataSync;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using DC_A95;
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
namespace MesWork
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 处理MIS逻辑
|
||||||
|
/// </summary>
|
||||||
|
public partial class MesWorkForm
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// PLC信号变化处理入口
|
||||||
|
/// 当Bool型信号值变化时由框架自动触发
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void MIS_Funtion(object e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var msgEvent = (DeviceDriver_BasicData.CustomeEvetnArgs)e;
|
||||||
|
if (msgEvent.TagValue == null) return;
|
||||||
|
var tagID = msgEvent.TagID.ToString();
|
||||||
|
var opName = msgEvent.OpName.ToString();
|
||||||
|
var tagTypeCodeID = (int)msgEvent.TagTypeCodeID;
|
||||||
|
var tagTypeID = (EnumTagTypeID)msgEvent.TagTypeID;
|
||||||
|
var isFirstValue = msgEvent.IsFirstValue.ToString().ToLower();
|
||||||
|
var alarmLevel = msgEvent.ShaftID.ToString();
|
||||||
|
var alarmMsg = msgEvent.ItemName.ToString();
|
||||||
|
string tagValue;
|
||||||
|
switch (tagTypeID)
|
||||||
|
{
|
||||||
|
case EnumTagTypeID.BOOL:
|
||||||
|
tagValue = (Convert.ToInt32(msgEvent.TagValue)).ToString();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tagValue = msgEvent.TagValue.ToString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// ── 报警处理(编码900~2000)──
|
||||||
|
if (tagTypeCodeID >= 900 & tagTypeCodeID < 2000)
|
||||||
|
{
|
||||||
|
if (ValueT(isFirstValue))
|
||||||
|
{
|
||||||
|
//不处理第一次变化的值
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var opNameNew = opName.Replace("_Alarm", "");
|
||||||
|
if (tagValue == "1")
|
||||||
|
{
|
||||||
|
B_DB_Opera.Event_Alarm_Start(opNameNew, tagTypeCodeID, alarmMsg, alarmLevel, tagID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
B_DB_Opera.Event_Alarm_End(opNameNew, tagTypeCodeID, alarmMsg, alarmLevel, tagID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ── 信号分发 ──
|
||||||
|
switch (tagTypeCodeID)
|
||||||
|
{
|
||||||
|
case 2: // 工件到位 → 启动/停止实时重量曲线采集
|
||||||
|
if (tagValue == "1")
|
||||||
|
{
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] 工件到位信号触发");
|
||||||
|
CurveCollector_Start(opName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CurveCollector_Stop(opName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 14: // PLC心跳 → 回写PC心跳
|
||||||
|
WritePLC_IF(15, opName, tagValue);
|
||||||
|
break;
|
||||||
|
case 44: // 请求工作
|
||||||
|
if (ValueT(isFirstValue)) return;
|
||||||
|
if (tagValue == "1")
|
||||||
|
{
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] PLC请求工作,开始处理...");
|
||||||
|
Weighing_HandleRequestWork(opName, tagID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WritePLC_IF(66, opName, false); //允许工作
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 19: // 请求保存
|
||||||
|
if (ValueT(isFirstValue)) return;
|
||||||
|
if (tagValue == "1")
|
||||||
|
{
|
||||||
|
CurveCollector_StopSampling(opName, true); // 先停止采样,保存完成后再关联称重记录ID
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] PLC请求保存数据...");
|
||||||
|
Weighing_HandleRequestSave(opName, tagID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WritePLC_IF(20, opName, false); //保存完成
|
||||||
|
WritePLC_IF(21, opName, false); //合格标志
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 203: // 设备状态
|
||||||
|
B_DB_Opera.Event_DeviceStatus_Change(opName, tagValue);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception err)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
// ====================================================================
|
||||||
|
// 称重交互核心方法
|
||||||
|
// ====================================================================
|
||||||
|
/// <summary>
|
||||||
|
/// 获取称重类型:地面/放油前/放油后
|
||||||
|
/// Ground模式:统一返回"地面"
|
||||||
|
/// Hanging模式:OP10=放油前,OP20=放油后
|
||||||
|
/// </summary>
|
||||||
|
private string GetWeighingType(string opName)
|
||||||
|
{
|
||||||
|
if (WeighingType == "Ground")
|
||||||
|
return "地面";
|
||||||
|
// Hanging模式
|
||||||
|
return opName == "OP10" ? "放油前" : "放油后";
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 处理请求工作信号 (tagTypeCodeID=44)
|
||||||
|
/// 流程:读取工件信息 → 查询参数 → 写过站记录 → 按类型处理称重记录 → 回写允许工作
|
||||||
|
/// </summary>
|
||||||
|
private void Weighing_HandleRequestWork(string opName, string tagID)
|
||||||
|
{
|
||||||
|
B_DB_Opera.SaveLog_Request(opName, Log_Type.ZK_MesHandler, "MIS_Function",
|
||||||
|
Log_FromAndTo.ZK, Log_FromAndTo.ZK, $"触发信号【44-请求工作】", out long AID);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 1. 读取PLC工件信息
|
||||||
|
string engineNo = PLC_R.GetString_CleanGarbled(ReadPLC(10, opName)); // 总成编号
|
||||||
|
string modelNo = PLC_R.GetString_CleanGarbled(ReadPLC(11, opName)); // 机型号
|
||||||
|
string orderNo = PLC_R.GetString_CleanGarbled(ReadPLC(39, opName)); // 工单号
|
||||||
|
string palletNo = PLC_R.GetString_CleanGarbled(ReadPLC(80, opName)); // 托盘号
|
||||||
|
B_DB_Opera.SaveLog_Response($"【{opName}】读取工件:发动机={engineNo},机型={modelNo},工单={orderNo},托盘={palletNo}", AID);
|
||||||
|
// 推送工件信息到称重UI
|
||||||
|
int stIdx = WeighingPage?.GetStationIndex(opName) ?? 1;
|
||||||
|
WeighingPage?.UpdateStationInfo(stIdx, engineNo, modelNo, orderNo);
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] 读取工件:{engineNo},机型={modelNo}");
|
||||||
|
// 2. 查询工件管理参数(加油量/抽油量/密度/残油量上下限)
|
||||||
|
if (!B_DB_Opera.QueryWorkpieceByModel(modelNo, out decimal addOilQty, out decimal extractOilQty, out decimal density,
|
||||||
|
out decimal residualOilUpperLimit, out decimal residualOilLowerLimit))
|
||||||
|
{
|
||||||
|
WritePLC_IF(112, opName, 3); // 报警代码=3,机型错误
|
||||||
|
B_DB_Opera.SaveLog_Response($"【{opName}】工件管理中未找到机型[{modelNo}]的参数,发动机={engineNo}", AID);
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] 机型[{modelNo}]未找到配置参数");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 3. 推送工件参数到UI
|
||||||
|
WeighingPage?.UpdateOilInfo(stIdx, addOilQty, extractOilQty, density, 0, 0);
|
||||||
|
// 4. 确定称重类型和工位名称
|
||||||
|
string weighType = GetWeighingType(opName); // 地面/放油前/放油后
|
||||||
|
string stationName = weighType; // 工位名称直接用称重类型名
|
||||||
|
// 4. 写过站记录(所有类型统一:INSERT一条,到达时间=NOW)
|
||||||
|
B_DB_Opera.InsertStationRecord(engineNo, modelNo, orderNo, palletNo,
|
||||||
|
opName, stationName, addOilQty, extractOilQty, density, Curr_UserName);
|
||||||
|
// 5. 按类型处理称重记录
|
||||||
|
if (weighType == "放油后")
|
||||||
|
{
|
||||||
|
// 空中放油后:查找最新放油前记录(无论是否完成,支持多次测量)
|
||||||
|
if (!B_DB_Opera.QueryWeighingBeforeOil(engineNo, out _, out decimal preWeight, out _, out _, out _))
|
||||||
|
{
|
||||||
|
// 写报警代码=3(发动机号错误),阻断流程
|
||||||
|
WritePLC_IF(112, opName, 3);
|
||||||
|
B_DB_Opera.SaveLog_Response($"【{opName}】未找到发动机[{engineNo}]的空中称重记录", AID);
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] 未找到[{engineNo}]放油前记录,进站失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
B_DB_Opera.SaveLog_Response($"【{opName}】空中放油后准备完成,发动机={engineNo},机型={modelNo},放油前重量={preWeight}kg", AID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 地面 或 空中放油前:每次都新建称重记录(支持同一产品多次测量取最新)
|
||||||
|
string recordType = weighType == "地面" ? "地面" : "空中";
|
||||||
|
B_DB_Opera.InsertWeighingRecord(opName, recordType, engineNo, modelNo, orderNo, palletNo,
|
||||||
|
0, 0, addOilQty, extractOilQty, density, residualOilUpperLimit, residualOilLowerLimit, 0, 0, 0, 0,
|
||||||
|
opName, Curr_UserName, isComplete: 0);
|
||||||
|
B_DB_Opera.SaveLog_Response($"【{opName}】{weighType}准备完成,发动机={engineNo},机型={modelNo},残油量范围={residualOilLowerLimit:F4}-{residualOilUpperLimit:F4}L", AID);
|
||||||
|
}
|
||||||
|
// 6. 回写允许工作
|
||||||
|
WritePLC_IF(66, opName, true);
|
||||||
|
}
|
||||||
|
catch (Exception err)
|
||||||
|
{
|
||||||
|
WritePLC_IF(112, opName, 1); // 报警代码=1,获取数据失败
|
||||||
|
B_DB_Opera.SaveLog_Response($"【{opName}】请求工作处理失败:{err.Message}", AID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 处理请求保存信号 (tagTypeCodeID=19)
|
||||||
|
/// 流程:读取称重数据 → 更新过站记录 → 按类型处理称重记录 → 回写保存完成
|
||||||
|
/// </summary>
|
||||||
|
private void Weighing_HandleRequestSave(string opName, string tagID)
|
||||||
|
{
|
||||||
|
B_DB_Opera.SaveLog_Request(opName, Log_Type.ZK_MesHandler, "MIS_Function",
|
||||||
|
Log_FromAndTo.ZK, Log_FromAndTo.ZK, $"触发信号【19-请求保存】", out long AID);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 1. 读取PLC数据
|
||||||
|
decimal weight = Convert.ToDecimal(ReadPLC(100140, opName)); // 重量
|
||||||
|
decimal waterContent = Convert.ToDecimal(ReadPLC(100180, opName)); // 水含量
|
||||||
|
string engineNo = PLC_R.GetString_CleanGarbled(ReadPLC(10, opName)); // 产品编号
|
||||||
|
long curveWeighingRecordId = 0;
|
||||||
|
// 2. 更新过站记录(离开时间+称重重量)
|
||||||
|
B_DB_Opera.UpdateStationComplete(engineNo, opName, weight);
|
||||||
|
// 3. 确定类型并处理
|
||||||
|
string weighType = GetWeighingType(opName);
|
||||||
|
decimal oilReleaseQty = 0;
|
||||||
|
decimal residualOilQty = 0;
|
||||||
|
int finalQualityFlag = 1;
|
||||||
|
string qualityMsg = "";
|
||||||
|
if (weighType == "地面")
|
||||||
|
{
|
||||||
|
// 地面:查最新记录 → 放油量=重量/密度 → 标记完成
|
||||||
|
B_DB_Opera.QueryLatestRecord(opName, engineNo,
|
||||||
|
out long recordId, out _, out decimal addOil, out decimal extractOil, out decimal dens);
|
||||||
|
curveWeighingRecordId = recordId;
|
||||||
|
oilReleaseQty = dens > 0 ? weight / dens : 0;
|
||||||
|
residualOilQty = addOil - extractOil - oilReleaseQty;
|
||||||
|
B_DB_Opera.UpdateWeighingComplete(recordId, "地面", opName,
|
||||||
|
weight, oilReleaseQty, residualOilQty, waterContent, out finalQualityFlag, out qualityMsg);
|
||||||
|
B_DB_Opera.SaveLog_Response(
|
||||||
|
$"【{opName}】地面保存完成:发动机={engineNo},重量={weight}kg,放油量={oilReleaseQty:F4}L,残油量={residualOilQty:F4}L,合格标志={finalQualityFlag},{qualityMsg}", AID);
|
||||||
|
WeighingPage?.UpdateOilResult(WeighingPage?.GetStationIndex(opName) ?? 1, oilReleaseQty, residualOilQty);
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] 保存完成:{engineNo},重量={weight:F2}kg,放油量={oilReleaseQty:F4}L");
|
||||||
|
}
|
||||||
|
else if (weighType == "放油前")
|
||||||
|
{
|
||||||
|
// 空中放油前:查最新记录 → 仅写入进站重量,不标记完成
|
||||||
|
B_DB_Opera.QueryLatestRecord(opName, engineNo,
|
||||||
|
out long recordId, out _, out _, out _, out _);
|
||||||
|
curveWeighingRecordId = recordId;
|
||||||
|
B_DB_Opera.UpdateWeighingComplete(recordId, "空中放油前", opName,
|
||||||
|
weight, 0, 0, waterContent, out finalQualityFlag, out qualityMsg);
|
||||||
|
B_DB_Opera.SaveLog_Response(
|
||||||
|
$"【{opName}】空中放油前保存完成:发动机={engineNo},进站重量={weight}kg,合格标志={finalQualityFlag},{qualityMsg}", AID);
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] 放油前保存:{engineNo},重量={weight:F2}kg");
|
||||||
|
}
|
||||||
|
else // 放油后
|
||||||
|
{
|
||||||
|
// 空中放油后:查最新放油前记录(无论是否完成),计算放油量更新到该记录
|
||||||
|
if (B_DB_Opera.QueryWeighingBeforeOil(engineNo, out long recordId, out decimal preWeight,
|
||||||
|
out decimal addOil, out decimal extractOil, out decimal dens))
|
||||||
|
{
|
||||||
|
curveWeighingRecordId = recordId;
|
||||||
|
oilReleaseQty = dens > 0 ? (preWeight - weight) / dens : 0;
|
||||||
|
residualOilQty = addOil - extractOil - oilReleaseQty;
|
||||||
|
B_DB_Opera.UpdateWeighingComplete(recordId, "空中放油后", opName,
|
||||||
|
weight, oilReleaseQty, residualOilQty, waterContent, out finalQualityFlag, out qualityMsg);
|
||||||
|
B_DB_Opera.SaveLog_Response(
|
||||||
|
$"【{opName}】空中放油后保存完成:发动机={engineNo},放油前={preWeight}kg,放油后={weight}kg,放油量={oilReleaseQty:F4}L,残油量={residualOilQty:F4}L,合格标志={finalQualityFlag},{qualityMsg}", AID);
|
||||||
|
WeighingPage?.UpdateOilResult(WeighingPage?.GetStationIndex(opName) ?? 1, oilReleaseQty, residualOilQty);
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] 放油后保存:{engineNo},放油量={oilReleaseQty:F4}L,残油量={residualOilQty:F4}L");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 找不到放油前记录(可能直接进OP20):创建一条放油后记录并标记完成
|
||||||
|
curveWeighingRecordId = B_DB_Opera.InsertWeighingRecord(opName, "空中放油后", engineNo, "", "", "",
|
||||||
|
0, weight, 0, 0, 0, 0, 0, 0, 0, 2, waterContent,
|
||||||
|
opName, Curr_UserName, isComplete: 1);
|
||||||
|
finalQualityFlag = 2;
|
||||||
|
qualityMsg = "未找到放油前记录";
|
||||||
|
B_DB_Opera.SaveLog_Response(
|
||||||
|
$"【{opName}】放油后保存(无放油前记录):发动机={engineNo},放油后重量={weight}kg", AID);
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] ⚠️ 放油后保存:{engineNo}(无放油前记录,已新建)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CurveCollector_EndSegment(opName, curveWeighingRecordId);
|
||||||
|
// TODO: MES接口数据上传(接口对接后实现)
|
||||||
|
if (finalQualityFlag == 2 && !string.IsNullOrWhiteSpace(qualityMsg))
|
||||||
|
{
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] 判定不合格:{qualityMsg}");
|
||||||
|
}
|
||||||
|
// 4. 先回写上位机判定的合格标志,再回写保存完成
|
||||||
|
WritePLC_IF(21, opName, finalQualityFlag);
|
||||||
|
WritePLC_IF(20, opName, true);
|
||||||
|
}
|
||||||
|
catch (Exception err)
|
||||||
|
{
|
||||||
|
CurveCollector_EndSegment(opName, 0);
|
||||||
|
WritePLC_IF(112, opName, 2); // 报警代码=2,保存失败
|
||||||
|
B_DB_Opera.SaveLog_Response($"【{opName}】保存处理失败:{err.Message}", AID);
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] ❌ 保存异常:{err.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====================================================================
|
||||||
|
// 扫码枪业务处理
|
||||||
|
// ====================================================================
|
||||||
|
/// <summary>
|
||||||
|
/// 扫码枪扫码完成后的业务处理
|
||||||
|
/// 将码值写入PLC地址102500,触发完成信号100016=1,1秒后复位
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opName">工位号(OP10/OP20),由COM口绑定决定</param>
|
||||||
|
/// <param name="barcode">扫到的条码值</param>
|
||||||
|
public void Barcode_HandleScan(string opName, string barcode)
|
||||||
|
{
|
||||||
|
B_DB_Opera.SaveLog_Request(opName, Log_Type.ZK_MesHandler, "MIS_Function",
|
||||||
|
Log_FromAndTo.ZK, Log_FromAndTo.ZK, $"扫码枪触发【{opName}】码值={barcode}", out long AID);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 1. 写入码值到 PLC 地址 102500(PLC_PC_扫码枪值)
|
||||||
|
WritePLC_IF(102500, opName, barcode);
|
||||||
|
// 2. 写入扫码完成信号 100016 = 1(PC_PLC_扫码枪扫码完成)
|
||||||
|
WritePLC_IF(100016, opName, true);
|
||||||
|
// 3. 日志
|
||||||
|
B_DB_Opera.SaveLog_Response($"【{opName}】扫码完成:码值={barcode}", AID);
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] 触发扫码 码值:{barcode}");
|
||||||
|
// 4. 1秒后复位 100016 = 0
|
||||||
|
System.Threading.Tasks.Task.Delay(1000).ContinueWith(_ =>
|
||||||
|
{
|
||||||
|
try { WritePLC_IF(100016, opName, false); }
|
||||||
|
catch { }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception err)
|
||||||
|
{
|
||||||
|
B_DB_Opera.SaveLog_Response($"【{opName}】扫码处理失败:{err.Message}", AID);
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] ❌ 扫码处理异常:{err.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CurveCollectorState
|
||||||
|
{
|
||||||
|
public string OpName;
|
||||||
|
public long SegmentId;
|
||||||
|
public Thread WorkerThread;
|
||||||
|
public volatile bool IsRunning;
|
||||||
|
public bool IsSegmentEnded;
|
||||||
|
public bool IsWaitingSave;
|
||||||
|
public int SeqNo;
|
||||||
|
public readonly object BufferLock = new object();
|
||||||
|
public readonly List<CurveSamplePoint> Buffer = new List<CurveSamplePoint>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly ConcurrentDictionary<string, CurveCollectorState> _curveCollectors
|
||||||
|
= new ConcurrentDictionary<string, CurveCollectorState>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 工件到位后启动实时重量曲线采集。
|
||||||
|
/// </summary>
|
||||||
|
private void CurveCollector_Start(string opName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_curveCollectors.TryGetValue(opName, out CurveCollectorState oldState) && !oldState.IsSegmentEnded)
|
||||||
|
{
|
||||||
|
if (oldState.IsRunning) return;
|
||||||
|
CurveCollector_EndSegment(opName, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
string engineNo = PLC_R.GetString_CleanGarbled(ReadPLC(10, opName));
|
||||||
|
string modelNo = PLC_R.GetString_CleanGarbled(ReadPLC(11, opName));
|
||||||
|
long segmentId = B_DB_Opera.Curve_StartSegment(opName, engineNo, modelNo);
|
||||||
|
if (segmentId <= 0)
|
||||||
|
{
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] 曲线段创建失败,未启动采集");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = new CurveCollectorState
|
||||||
|
{
|
||||||
|
OpName = opName,
|
||||||
|
SegmentId = segmentId,
|
||||||
|
IsRunning = true
|
||||||
|
};
|
||||||
|
state.WorkerThread = new Thread(() => CurveCollector_Work(state))
|
||||||
|
{
|
||||||
|
IsBackground = true,
|
||||||
|
Name = $"CurveCollector_{opName}"
|
||||||
|
};
|
||||||
|
|
||||||
|
_curveCollectors[opName] = state;
|
||||||
|
state.WorkerThread.Start();
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] 实时重量曲线采集启动,段ID={segmentId}");
|
||||||
|
}
|
||||||
|
catch (Exception err)
|
||||||
|
{
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] 曲线采集启动异常:{err.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 采集线程:200ms读取一次实时重量,满10条批量写库。
|
||||||
|
/// </summary>
|
||||||
|
private void CurveCollector_Work(CurveCollectorState state)
|
||||||
|
{
|
||||||
|
while (state.IsRunning)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
decimal weight = Convert.ToDecimal(ReadPLC(100220, state.OpName));
|
||||||
|
List<CurveSamplePoint> writePoints = null;
|
||||||
|
lock (state.BufferLock)
|
||||||
|
{
|
||||||
|
state.Buffer.Add(new CurveSamplePoint
|
||||||
|
{
|
||||||
|
SeqNo = ++state.SeqNo,
|
||||||
|
SampleTime = DateTime.Now,
|
||||||
|
Weight = weight
|
||||||
|
});
|
||||||
|
if (state.Buffer.Count >= 10)
|
||||||
|
{
|
||||||
|
writePoints = new List<CurveSamplePoint>(state.Buffer);
|
||||||
|
state.Buffer.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writePoints != null)
|
||||||
|
{
|
||||||
|
B_DB_Opera.Curve_WritePoints(state.SegmentId, writePoints);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception err)
|
||||||
|
{
|
||||||
|
WeighingPage?.AppendLog($"[{state.OpName}] 曲线采样异常:{err.Message}");
|
||||||
|
}
|
||||||
|
Thread.Sleep(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
CurveCollector_Flush(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 停止采样线程并刷出剩余点,但暂不关闭曲线段。
|
||||||
|
/// </summary>
|
||||||
|
private void CurveCollector_StopSampling(string opName, bool waitingSave = false)
|
||||||
|
{
|
||||||
|
if (!_curveCollectors.TryGetValue(opName, out CurveCollectorState state)) return;
|
||||||
|
|
||||||
|
if (waitingSave)
|
||||||
|
{
|
||||||
|
state.IsWaitingSave = true;
|
||||||
|
}
|
||||||
|
state.IsRunning = false;
|
||||||
|
if (state.WorkerThread != null && state.WorkerThread.IsAlive)
|
||||||
|
{
|
||||||
|
state.WorkerThread.Join(2000);
|
||||||
|
}
|
||||||
|
CurveCollector_Flush(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 工件离开时停止采集并关闭曲线段。
|
||||||
|
/// </summary>
|
||||||
|
private void CurveCollector_Stop(string opName)
|
||||||
|
{
|
||||||
|
if (_curveCollectors.TryGetValue(opName, out CurveCollectorState state) && state.IsWaitingSave)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CurveCollector_EndSegment(opName, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存完成后关闭曲线段,并关联称重记录ID。
|
||||||
|
/// </summary>
|
||||||
|
private void CurveCollector_EndSegment(string opName, long weighingRecordId)
|
||||||
|
{
|
||||||
|
if (!_curveCollectors.TryGetValue(opName, out CurveCollectorState state)) return;
|
||||||
|
|
||||||
|
CurveCollector_StopSampling(opName);
|
||||||
|
if (!state.IsSegmentEnded)
|
||||||
|
{
|
||||||
|
B_DB_Opera.Curve_EndSegment(state.SegmentId, weighingRecordId);
|
||||||
|
state.IsSegmentEnded = true;
|
||||||
|
WeighingPage?.AppendLog($"[{opName}] 实时重量曲线采集结束,段ID={state.SegmentId}");
|
||||||
|
}
|
||||||
|
_curveCollectors.TryRemove(opName, out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将采集缓冲区剩余点写入数据库。
|
||||||
|
/// </summary>
|
||||||
|
private void CurveCollector_Flush(CurveCollectorState state)
|
||||||
|
{
|
||||||
|
List<CurveSamplePoint> writePoints = null;
|
||||||
|
lock (state.BufferLock)
|
||||||
|
{
|
||||||
|
if (state.Buffer.Count > 0)
|
||||||
|
{
|
||||||
|
writePoints = new List<CurveSamplePoint>(state.Buffer);
|
||||||
|
state.Buffer.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writePoints != null)
|
||||||
|
{
|
||||||
|
B_DB_Opera.Curve_WritePoints(state.SegmentId, writePoints);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
518
SCADA/MAIN_PAGE.Designer.cs
generated
Normal file
518
SCADA/MAIN_PAGE.Designer.cs
generated
Normal file
@@ -0,0 +1,518 @@
|
|||||||
|
using System.Windows.Forms;
|
||||||
|
namespace MesWork
|
||||||
|
{
|
||||||
|
partial class MesWorkForm : PlcLinkForm
|
||||||
|
{
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows 窗体设计器生成的代码
|
||||||
|
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
|
||||||
|
// ── Timers ──
|
||||||
|
this.timer_OnLine_Show = new System.Windows.Forms.Timer(this.components);
|
||||||
|
this.timer_Clock = new System.Windows.Forms.Timer(this.components);
|
||||||
|
|
||||||
|
// ── Top Bar ──
|
||||||
|
this.pnl_TopBar = new System.Windows.Forms.Panel();
|
||||||
|
this.pnl_TopBarRight = new System.Windows.Forms.Panel();
|
||||||
|
this.lbl_SystemTitle = new System.Windows.Forms.Label();
|
||||||
|
this.lbl_DateTime = new System.Windows.Forms.Label();
|
||||||
|
this.lbl_UserName = new System.Windows.Forms.Label();
|
||||||
|
this.pnl_SqlIndicator = new System.Windows.Forms.Panel();
|
||||||
|
this.lbl_SqlStatus = new System.Windows.Forms.Label();
|
||||||
|
|
||||||
|
// ── Sidebar ──
|
||||||
|
this.pnl_Sidebar = new System.Windows.Forms.Panel();
|
||||||
|
this.pnl_SidebarScroll = new System.Windows.Forms.Panel();
|
||||||
|
this.pnl_NavWeighing = new System.Windows.Forms.Panel();
|
||||||
|
this.lbl_NavWeighing = new System.Windows.Forms.Label();
|
||||||
|
this.pnl_NavUserMgmt = new System.Windows.Forms.Panel();
|
||||||
|
this.lbl_NavUserMgmt = new System.Windows.Forms.Label();
|
||||||
|
this.pnl_NavWorkpiece = new System.Windows.Forms.Panel();
|
||||||
|
this.lbl_NavWorkpiece = new System.Windows.Forms.Label();
|
||||||
|
this.pnl_NavTool = new System.Windows.Forms.Panel();
|
||||||
|
this.lbl_NavTool = new System.Windows.Forms.Label();
|
||||||
|
this.pnl_NavReport = new System.Windows.Forms.Panel();
|
||||||
|
this.lbl_NavReport = new System.Windows.Forms.Label();
|
||||||
|
this.pnl_NavStation = new System.Windows.Forms.Panel();
|
||||||
|
this.lbl_NavStation = new System.Windows.Forms.Label();
|
||||||
|
this.pnl_NavStatistics = new System.Windows.Forms.Panel();
|
||||||
|
this.lbl_NavStatistics = new System.Windows.Forms.Label();
|
||||||
|
this.pnl_NavSettings = new System.Windows.Forms.Panel();
|
||||||
|
this.lbl_NavSettings = new System.Windows.Forms.Label();
|
||||||
|
this.pnl_NavLog = new System.Windows.Forms.Panel();
|
||||||
|
this.lbl_NavLog = new System.Windows.Forms.Label();
|
||||||
|
this.pnl_NavPLC = new System.Windows.Forms.Panel();
|
||||||
|
this.lbl_NavPLC = new System.Windows.Forms.Label();
|
||||||
|
this.pnl_NavFullscreen = new System.Windows.Forms.Panel();
|
||||||
|
this.lbl_NavFullscreen = new System.Windows.Forms.Label();
|
||||||
|
this.pnl_NavClose = new System.Windows.Forms.Panel();
|
||||||
|
this.lbl_NavClose = new System.Windows.Forms.Label();
|
||||||
|
this.pnl_NavActiveIndicator = new System.Windows.Forms.Panel();
|
||||||
|
|
||||||
|
// ── Alarm Bar ──
|
||||||
|
this.panel_Alarm = new System.Windows.Forms.Panel();
|
||||||
|
this.label_Alarm = new System.Windows.Forms.Label();
|
||||||
|
this.lbl_AlarmIcon = new System.Windows.Forms.Label();
|
||||||
|
|
||||||
|
// ── Content ──
|
||||||
|
this.pnl_Content = new System.Windows.Forms.Panel();
|
||||||
|
|
||||||
|
this.pnl_TopBar.SuspendLayout();
|
||||||
|
this.pnl_TopBarRight.SuspendLayout();
|
||||||
|
this.pnl_Sidebar.SuspendLayout();
|
||||||
|
this.pnl_SidebarScroll.SuspendLayout();
|
||||||
|
this.panel_Alarm.SuspendLayout();
|
||||||
|
this.SuspendLayout();
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// timer_OnLine_Show — 框架心跳/SQL检测
|
||||||
|
// ====================================================================
|
||||||
|
this.timer_OnLine_Show.Interval = 1000;
|
||||||
|
this.timer_OnLine_Show.Tick += new System.EventHandler(this.timer_OnLine_Show_Tick);
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// timer_Clock — 时钟刷新
|
||||||
|
// ====================================================================
|
||||||
|
this.timer_Clock.Interval = 1000;
|
||||||
|
this.timer_Clock.Tick += new System.EventHandler(this.timer_Clock_Tick);
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// pnl_TopBar — 顶部标题栏 (48px)
|
||||||
|
// ====================================================================
|
||||||
|
this.pnl_TopBar.BackColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.pnl_TopBar.Dock = System.Windows.Forms.DockStyle.Top;
|
||||||
|
this.pnl_TopBar.Height = 48;
|
||||||
|
this.pnl_TopBar.Name = "pnl_TopBar";
|
||||||
|
this.pnl_TopBar.Controls.Add(this.lbl_SystemTitle);
|
||||||
|
this.pnl_TopBar.Controls.Add(this.pnl_TopBarRight);
|
||||||
|
|
||||||
|
// lbl_SystemTitle
|
||||||
|
this.lbl_SystemTitle.AutoSize = false;
|
||||||
|
this.lbl_SystemTitle.Font = new System.Drawing.Font("微软雅黑", 14F, System.Drawing.FontStyle.Bold);
|
||||||
|
this.lbl_SystemTitle.ForeColor = System.Drawing.Color.White;
|
||||||
|
this.lbl_SystemTitle.Location = new System.Drawing.Point(92, 0);
|
||||||
|
this.lbl_SystemTitle.Size = new System.Drawing.Size(400, 48);
|
||||||
|
this.lbl_SystemTitle.Name = "lbl_SystemTitle";
|
||||||
|
this.lbl_SystemTitle.Text = "⚖ 称重数据采集分析管理系统";
|
||||||
|
this.lbl_SystemTitle.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||||
|
|
||||||
|
// ── pnl_TopBarRight — 右侧控件容器(Dock=Right,确保任何分辨率可见)──
|
||||||
|
this.pnl_TopBarRight.BackColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.pnl_TopBarRight.Dock = System.Windows.Forms.DockStyle.Right;
|
||||||
|
this.pnl_TopBarRight.Width = 420;
|
||||||
|
this.pnl_TopBarRight.Name = "pnl_TopBarRight";
|
||||||
|
this.pnl_TopBarRight.Controls.Add(this.pnl_SqlIndicator);
|
||||||
|
this.pnl_TopBarRight.Controls.Add(this.lbl_SqlStatus);
|
||||||
|
this.pnl_TopBarRight.Controls.Add(this.lbl_UserName);
|
||||||
|
this.pnl_TopBarRight.Controls.Add(this.lbl_DateTime);
|
||||||
|
|
||||||
|
// pnl_SqlIndicator — 数据库在线指示灯
|
||||||
|
this.pnl_SqlIndicator.BackColor = System.Drawing.Color.FromArgb(209, 213, 219);
|
||||||
|
this.pnl_SqlIndicator.Location = new System.Drawing.Point(10, 17);
|
||||||
|
this.pnl_SqlIndicator.Size = new System.Drawing.Size(14, 14);
|
||||||
|
this.pnl_SqlIndicator.Name = "pnl_SqlIndicator";
|
||||||
|
|
||||||
|
// lbl_SqlStatus — 数据库状态标签
|
||||||
|
this.lbl_SqlStatus.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||||
|
this.lbl_SqlStatus.ForeColor = System.Drawing.Color.FromArgb(148, 163, 184);
|
||||||
|
this.lbl_SqlStatus.Location = new System.Drawing.Point(28, 0);
|
||||||
|
this.lbl_SqlStatus.Size = new System.Drawing.Size(55, 48);
|
||||||
|
this.lbl_SqlStatus.Name = "lbl_SqlStatus";
|
||||||
|
this.lbl_SqlStatus.Text = "数据库";
|
||||||
|
this.lbl_SqlStatus.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||||
|
|
||||||
|
// lbl_UserName
|
||||||
|
this.lbl_UserName.Font = new System.Drawing.Font("微软雅黑", 10F);
|
||||||
|
this.lbl_UserName.ForeColor = System.Drawing.Color.FromArgb(148, 163, 184);
|
||||||
|
this.lbl_UserName.Location = new System.Drawing.Point(90, 0);
|
||||||
|
this.lbl_UserName.Size = new System.Drawing.Size(160, 48);
|
||||||
|
this.lbl_UserName.Name = "lbl_UserName";
|
||||||
|
this.lbl_UserName.Text = "操作员:";
|
||||||
|
this.lbl_UserName.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
|
||||||
|
// lbl_DateTime
|
||||||
|
this.lbl_DateTime.Font = new System.Drawing.Font("微软雅黑", 10F);
|
||||||
|
this.lbl_DateTime.ForeColor = System.Drawing.Color.FromArgb(148, 163, 184);
|
||||||
|
this.lbl_DateTime.Location = new System.Drawing.Point(250, 0);
|
||||||
|
this.lbl_DateTime.Size = new System.Drawing.Size(165, 48);
|
||||||
|
this.lbl_DateTime.Name = "lbl_DateTime";
|
||||||
|
this.lbl_DateTime.Text = "2026-04-07 20:00:00";
|
||||||
|
this.lbl_DateTime.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// pnl_Sidebar — 左侧导航栏 (80px, Navy背景)
|
||||||
|
// ====================================================================
|
||||||
|
this.pnl_Sidebar.BackColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.pnl_Sidebar.Dock = System.Windows.Forms.DockStyle.Left;
|
||||||
|
this.pnl_Sidebar.Width = 80;
|
||||||
|
this.pnl_Sidebar.Name = "pnl_Sidebar";
|
||||||
|
// 全屏+退出 固定在侧栏底部
|
||||||
|
this.pnl_NavFullscreen.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||||
|
this.pnl_NavFullscreen.Size = new System.Drawing.Size(80, 44);
|
||||||
|
this.pnl_NavClose.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||||
|
this.pnl_NavClose.Size = new System.Drawing.Size(80, 44);
|
||||||
|
this.pnl_Sidebar.Controls.Add(this.pnl_SidebarScroll);
|
||||||
|
this.pnl_Sidebar.Controls.Add(this.pnl_NavFullscreen);
|
||||||
|
this.pnl_Sidebar.Controls.Add(this.pnl_NavClose);
|
||||||
|
|
||||||
|
// pnl_SidebarScroll — 内部滚动容器
|
||||||
|
this.pnl_SidebarScroll.AutoScroll = true;
|
||||||
|
this.pnl_SidebarScroll.BackColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.pnl_SidebarScroll.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.pnl_SidebarScroll.Name = "pnl_SidebarScroll";
|
||||||
|
|
||||||
|
// ── 导航项:称重作业 ──
|
||||||
|
this.pnl_NavWeighing.BackColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.pnl_NavWeighing.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavWeighing.Location = new System.Drawing.Point(1, 8);
|
||||||
|
this.pnl_NavWeighing.Size = new System.Drawing.Size(78, 64);
|
||||||
|
this.pnl_NavWeighing.Name = "pnl_NavWeighing";
|
||||||
|
this.pnl_NavWeighing.Tag = "⚖\n称重作业";
|
||||||
|
this.lbl_NavWeighing.AutoSize = false;
|
||||||
|
this.lbl_NavWeighing.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.lbl_NavWeighing.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||||
|
this.lbl_NavWeighing.ForeColor = System.Drawing.Color.FromArgb(148, 163, 184);
|
||||||
|
this.lbl_NavWeighing.Text = "⚖\n称重作业";
|
||||||
|
this.lbl_NavWeighing.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
this.lbl_NavWeighing.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavWeighing.Controls.Add(this.lbl_NavWeighing);
|
||||||
|
// ── 导航项:用户管理 ──
|
||||||
|
this.pnl_NavUserMgmt.BackColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.pnl_NavUserMgmt.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavUserMgmt.Location = new System.Drawing.Point(1, 74);
|
||||||
|
this.pnl_NavUserMgmt.Size = new System.Drawing.Size(78, 64);
|
||||||
|
this.pnl_NavUserMgmt.Name = "pnl_NavUserMgmt";
|
||||||
|
this.pnl_NavUserMgmt.Tag = "👤\n用户管理";
|
||||||
|
this.lbl_NavUserMgmt.AutoSize = false;
|
||||||
|
this.lbl_NavUserMgmt.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.lbl_NavUserMgmt.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||||
|
this.lbl_NavUserMgmt.ForeColor = System.Drawing.Color.FromArgb(148, 163, 184);
|
||||||
|
this.lbl_NavUserMgmt.Text = "👤\n用户管理";
|
||||||
|
this.lbl_NavUserMgmt.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
this.lbl_NavUserMgmt.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavUserMgmt.Controls.Add(this.lbl_NavUserMgmt);
|
||||||
|
// ── 导航项:工件管理 ──
|
||||||
|
this.pnl_NavWorkpiece.BackColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.pnl_NavWorkpiece.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavWorkpiece.Location = new System.Drawing.Point(1, 140);
|
||||||
|
this.pnl_NavWorkpiece.Size = new System.Drawing.Size(78, 64);
|
||||||
|
this.pnl_NavWorkpiece.Name = "pnl_NavWorkpiece";
|
||||||
|
this.pnl_NavWorkpiece.Tag = "⚙\n工件管理";
|
||||||
|
this.lbl_NavWorkpiece.AutoSize = false;
|
||||||
|
this.lbl_NavWorkpiece.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.lbl_NavWorkpiece.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||||
|
this.lbl_NavWorkpiece.ForeColor = System.Drawing.Color.FromArgb(148, 163, 184);
|
||||||
|
this.lbl_NavWorkpiece.Text = "⚙\n工件管理";
|
||||||
|
this.lbl_NavWorkpiece.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
this.lbl_NavWorkpiece.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavWorkpiece.Controls.Add(this.lbl_NavWorkpiece);
|
||||||
|
// ── 导航项:工具管理 ──
|
||||||
|
this.pnl_NavTool.BackColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.pnl_NavTool.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavTool.Location = new System.Drawing.Point(1, 206);
|
||||||
|
this.pnl_NavTool.Size = new System.Drawing.Size(78, 64);
|
||||||
|
this.pnl_NavTool.Name = "pnl_NavTool";
|
||||||
|
this.pnl_NavTool.Tag = "🔧\n工具管理";
|
||||||
|
this.lbl_NavTool.AutoSize = false;
|
||||||
|
this.lbl_NavTool.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.lbl_NavTool.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||||
|
this.lbl_NavTool.ForeColor = System.Drawing.Color.FromArgb(148, 163, 184);
|
||||||
|
this.lbl_NavTool.Text = "🔧\n工具管理";
|
||||||
|
this.lbl_NavTool.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
this.lbl_NavTool.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavTool.Controls.Add(this.lbl_NavTool);
|
||||||
|
// ── 导航项:报告查询 ──
|
||||||
|
this.pnl_NavReport.BackColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.pnl_NavReport.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavReport.Location = new System.Drawing.Point(1, 272);
|
||||||
|
this.pnl_NavReport.Size = new System.Drawing.Size(78, 64);
|
||||||
|
this.pnl_NavReport.Name = "pnl_NavReport";
|
||||||
|
this.pnl_NavReport.Tag = "📋\n报告查询";
|
||||||
|
this.lbl_NavReport.AutoSize = false;
|
||||||
|
this.lbl_NavReport.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.lbl_NavReport.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||||
|
this.lbl_NavReport.ForeColor = System.Drawing.Color.FromArgb(148, 163, 184);
|
||||||
|
this.lbl_NavReport.Text = "📋\n报告查询";
|
||||||
|
this.lbl_NavReport.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
this.lbl_NavReport.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavReport.Controls.Add(this.lbl_NavReport);
|
||||||
|
// ── 导航项:过站记录 ──
|
||||||
|
this.pnl_NavStation.BackColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.pnl_NavStation.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavStation.Location = new System.Drawing.Point(1, 338);
|
||||||
|
this.pnl_NavStation.Size = new System.Drawing.Size(78, 64);
|
||||||
|
this.pnl_NavStation.Name = "pnl_NavStation";
|
||||||
|
this.pnl_NavStation.Tag = "📦\n过站记录";
|
||||||
|
this.lbl_NavStation.AutoSize = false;
|
||||||
|
this.lbl_NavStation.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.lbl_NavStation.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||||
|
this.lbl_NavStation.ForeColor = System.Drawing.Color.FromArgb(148, 163, 184);
|
||||||
|
this.lbl_NavStation.Text = "📦\n过站记录";
|
||||||
|
this.lbl_NavStation.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
this.lbl_NavStation.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavStation.Controls.Add(this.lbl_NavStation);
|
||||||
|
// ── 导航项:统计分析 ──
|
||||||
|
this.pnl_NavStatistics.BackColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.pnl_NavStatistics.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavStatistics.Location = new System.Drawing.Point(1, 404);
|
||||||
|
this.pnl_NavStatistics.Size = new System.Drawing.Size(78, 64);
|
||||||
|
this.pnl_NavStatistics.Name = "pnl_NavStatistics";
|
||||||
|
this.pnl_NavStatistics.Tag = "📊\n统计分析";
|
||||||
|
this.lbl_NavStatistics.AutoSize = false;
|
||||||
|
this.lbl_NavStatistics.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.lbl_NavStatistics.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||||
|
this.lbl_NavStatistics.ForeColor = System.Drawing.Color.FromArgb(148, 163, 184);
|
||||||
|
this.lbl_NavStatistics.Text = "📊\n统计分析";
|
||||||
|
this.lbl_NavStatistics.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
this.lbl_NavStatistics.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavStatistics.Controls.Add(this.lbl_NavStatistics);
|
||||||
|
// ── 导航项:系统设置 ──
|
||||||
|
this.pnl_NavSettings.BackColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.pnl_NavSettings.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavSettings.Location = new System.Drawing.Point(1, 470);
|
||||||
|
this.pnl_NavSettings.Size = new System.Drawing.Size(78, 64);
|
||||||
|
this.pnl_NavSettings.Name = "pnl_NavSettings";
|
||||||
|
this.pnl_NavSettings.Tag = "⚙\n系统设置";
|
||||||
|
this.lbl_NavSettings.AutoSize = false;
|
||||||
|
this.lbl_NavSettings.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.lbl_NavSettings.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||||
|
this.lbl_NavSettings.ForeColor = System.Drawing.Color.FromArgb(148, 163, 184);
|
||||||
|
this.lbl_NavSettings.Text = "⚙\n系统设置";
|
||||||
|
this.lbl_NavSettings.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
this.lbl_NavSettings.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavSettings.Controls.Add(this.lbl_NavSettings);
|
||||||
|
// ── 导航项:日志查询 ──
|
||||||
|
this.pnl_NavLog.BackColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.pnl_NavLog.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavLog.Location = new System.Drawing.Point(1, 536);
|
||||||
|
this.pnl_NavLog.Size = new System.Drawing.Size(78, 64);
|
||||||
|
this.pnl_NavLog.Name = "pnl_NavLog";
|
||||||
|
this.pnl_NavLog.Tag = "📝\n日志查询";
|
||||||
|
this.lbl_NavLog.AutoSize = false;
|
||||||
|
this.lbl_NavLog.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.lbl_NavLog.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||||
|
this.lbl_NavLog.ForeColor = System.Drawing.Color.FromArgb(148, 163, 184);
|
||||||
|
this.lbl_NavLog.Text = "📝\n日志查询";
|
||||||
|
this.lbl_NavLog.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
this.lbl_NavLog.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavLog.Controls.Add(this.lbl_NavLog);
|
||||||
|
// ── 导航项:PLC监控 ──
|
||||||
|
this.pnl_NavPLC.BackColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.pnl_NavPLC.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavPLC.Location = new System.Drawing.Point(1, 602);
|
||||||
|
this.pnl_NavPLC.Size = new System.Drawing.Size(78, 64);
|
||||||
|
this.pnl_NavPLC.Name = "pnl_NavPLC";
|
||||||
|
this.pnl_NavPLC.Tag = "📡\nPLC监控";
|
||||||
|
this.lbl_NavPLC.AutoSize = false;
|
||||||
|
this.lbl_NavPLC.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.lbl_NavPLC.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||||
|
this.lbl_NavPLC.ForeColor = System.Drawing.Color.FromArgb(148, 163, 184);
|
||||||
|
this.lbl_NavPLC.Text = "📡\nPLC监控";
|
||||||
|
this.lbl_NavPLC.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
this.lbl_NavPLC.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavPLC.Controls.Add(this.lbl_NavPLC);
|
||||||
|
// ── 全屏按钮(固定在侧栏底部,退出按钮上方) ──
|
||||||
|
this.pnl_NavFullscreen.BackColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.pnl_NavFullscreen.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavFullscreen.Name = "pnl_NavFullscreen";
|
||||||
|
this.lbl_NavFullscreen.AutoSize = false;
|
||||||
|
this.lbl_NavFullscreen.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.lbl_NavFullscreen.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||||
|
this.lbl_NavFullscreen.ForeColor = System.Drawing.Color.FromArgb(148, 163, 184);
|
||||||
|
this.lbl_NavFullscreen.Text = "▣\n全屏";
|
||||||
|
this.lbl_NavFullscreen.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
this.lbl_NavFullscreen.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavFullscreen.Controls.Add(this.lbl_NavFullscreen);
|
||||||
|
// ── 退出按钮(固定在侧栏底部) ──
|
||||||
|
this.pnl_NavClose.BackColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.pnl_NavClose.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavClose.Name = "pnl_NavClose";
|
||||||
|
this.pnl_NavClose.Tag = "✕\n退出";
|
||||||
|
this.lbl_NavClose.AutoSize = false;
|
||||||
|
this.lbl_NavClose.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.lbl_NavClose.Font = new System.Drawing.Font("微软雅黑", 9F);
|
||||||
|
this.lbl_NavClose.ForeColor = System.Drawing.Color.FromArgb(239, 68, 68);
|
||||||
|
this.lbl_NavClose.Text = "✕\n退出";
|
||||||
|
this.lbl_NavClose.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
this.lbl_NavClose.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.pnl_NavClose.Controls.Add(this.lbl_NavClose);
|
||||||
|
|
||||||
|
// 导航Active指示条(4px宽蓝色条,初始隐藏,后续代码定位)
|
||||||
|
this.pnl_NavActiveIndicator.BackColor = System.Drawing.Color.FromArgb(74, 144, 217);
|
||||||
|
this.pnl_NavActiveIndicator.Location = new System.Drawing.Point(0, 8);
|
||||||
|
this.pnl_NavActiveIndicator.Size = new System.Drawing.Size(4, 64);
|
||||||
|
this.pnl_NavActiveIndicator.Name = "pnl_NavActiveIndicator";
|
||||||
|
|
||||||
|
// 添加导航项到滚动容器(从下往上加,确保绘制顺序)
|
||||||
|
this.pnl_SidebarScroll.Controls.Add(this.pnl_NavActiveIndicator);
|
||||||
|
// pnl_NavClose 已从滚动容器移出到pnl_Sidebar底部
|
||||||
|
this.pnl_SidebarScroll.Controls.Add(this.pnl_NavPLC);
|
||||||
|
this.pnl_SidebarScroll.Controls.Add(this.pnl_NavLog);
|
||||||
|
this.pnl_SidebarScroll.Controls.Add(this.pnl_NavSettings);
|
||||||
|
this.pnl_SidebarScroll.Controls.Add(this.pnl_NavStatistics);
|
||||||
|
this.pnl_SidebarScroll.Controls.Add(this.pnl_NavStation);
|
||||||
|
this.pnl_SidebarScroll.Controls.Add(this.pnl_NavReport);
|
||||||
|
this.pnl_SidebarScroll.Controls.Add(this.pnl_NavTool);
|
||||||
|
this.pnl_SidebarScroll.Controls.Add(this.pnl_NavWorkpiece);
|
||||||
|
this.pnl_SidebarScroll.Controls.Add(this.pnl_NavUserMgmt);
|
||||||
|
this.pnl_SidebarScroll.Controls.Add(this.pnl_NavWeighing);
|
||||||
|
|
||||||
|
// 绑定导航点击事件
|
||||||
|
this.pnl_NavWeighing.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.lbl_NavWeighing.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.pnl_NavUserMgmt.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.lbl_NavUserMgmt.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.pnl_NavWorkpiece.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.lbl_NavWorkpiece.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.pnl_NavTool.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.lbl_NavTool.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.pnl_NavReport.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.lbl_NavReport.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.pnl_NavStation.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.lbl_NavStation.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.pnl_NavStatistics.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.lbl_NavStatistics.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.pnl_NavSettings.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.lbl_NavSettings.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.pnl_NavLog.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.lbl_NavLog.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.pnl_NavPLC.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.lbl_NavPLC.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.pnl_NavFullscreen.Click += new System.EventHandler(this.btn_ToggleFullscreen_Click);
|
||||||
|
this.lbl_NavFullscreen.Click += new System.EventHandler(this.btn_ToggleFullscreen_Click);
|
||||||
|
this.pnl_NavClose.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
this.lbl_NavClose.Click += new System.EventHandler(this.Nav_Click);
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// panel_Alarm — 底部报警栏 (32px)
|
||||||
|
// ====================================================================
|
||||||
|
this.panel_Alarm.BackColor = System.Drawing.Color.FromArgb(30, 58, 95);
|
||||||
|
this.panel_Alarm.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||||
|
this.panel_Alarm.Height = 32;
|
||||||
|
this.panel_Alarm.Name = "panel_Alarm";
|
||||||
|
this.panel_Alarm.Controls.Add(this.label_Alarm);
|
||||||
|
this.panel_Alarm.Controls.Add(this.lbl_AlarmIcon);
|
||||||
|
|
||||||
|
// lbl_AlarmIcon
|
||||||
|
this.lbl_AlarmIcon.Font = new System.Drawing.Font("微软雅黑", 10F);
|
||||||
|
this.lbl_AlarmIcon.ForeColor = System.Drawing.Color.White;
|
||||||
|
this.lbl_AlarmIcon.Location = new System.Drawing.Point(4, 0);
|
||||||
|
this.lbl_AlarmIcon.Size = new System.Drawing.Size(80, 32);
|
||||||
|
this.lbl_AlarmIcon.Name = "lbl_AlarmIcon";
|
||||||
|
this.lbl_AlarmIcon.Text = "🔔 报警";
|
||||||
|
this.lbl_AlarmIcon.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||||
|
|
||||||
|
// label_Alarm — 保持原名以兼容 AppConfig.cs 中的引用
|
||||||
|
this.label_Alarm.Anchor = System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right | System.Windows.Forms.AnchorStyles.Top;
|
||||||
|
this.label_Alarm.Font = new System.Drawing.Font("微软雅黑", 10F);
|
||||||
|
this.label_Alarm.ForeColor = System.Drawing.Color.White;
|
||||||
|
this.label_Alarm.Location = new System.Drawing.Point(88, 0);
|
||||||
|
this.label_Alarm.Size = new System.Drawing.Size(1800, 32);
|
||||||
|
this.label_Alarm.Name = "label_Alarm";
|
||||||
|
this.label_Alarm.Text = "";
|
||||||
|
this.label_Alarm.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// pnl_Content — 主内容区域 (动态加载UserControl)
|
||||||
|
// ====================================================================
|
||||||
|
this.pnl_Content.BackColor = System.Drawing.Color.FromArgb(245, 247, 250);
|
||||||
|
this.pnl_Content.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.pnl_Content.Name = "pnl_Content";
|
||||||
|
this.pnl_Content.Padding = new System.Windows.Forms.Padding(8);
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// MesWorkForm — 主窗口
|
||||||
|
// ====================================================================
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||||
|
this.ClientSize = new System.Drawing.Size(1920, 1080);
|
||||||
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable;
|
||||||
|
this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
|
||||||
|
this.Name = "MesWorkForm";
|
||||||
|
this.Text = "称重数据采集分析管理系统";
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||||
|
|
||||||
|
// 添加顺序:先Dock的后Add(Fill最后被添加但先占位)
|
||||||
|
// 正确顺序:Content(Fill) → Sidebar(Left) → Alarm(Bottom) → TopBar(Top)
|
||||||
|
this.Controls.Add(this.pnl_Content);
|
||||||
|
this.Controls.Add(this.pnl_Sidebar);
|
||||||
|
this.Controls.Add(this.panel_Alarm);
|
||||||
|
this.Controls.Add(this.pnl_TopBar);
|
||||||
|
|
||||||
|
this.Load += new System.EventHandler(this.MesWorkForm_Load);
|
||||||
|
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MesWorkForm_FormClosing);
|
||||||
|
|
||||||
|
this.pnl_TopBar.ResumeLayout(false);
|
||||||
|
this.pnl_TopBarRight.ResumeLayout(false);
|
||||||
|
this.pnl_Sidebar.ResumeLayout(false);
|
||||||
|
this.pnl_SidebarScroll.ResumeLayout(false);
|
||||||
|
this.panel_Alarm.ResumeLayout(false);
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
// ── Timers ──
|
||||||
|
private System.Windows.Forms.Timer timer_OnLine_Show;
|
||||||
|
private System.Windows.Forms.Timer timer_Clock;
|
||||||
|
|
||||||
|
// ── Top Bar ──
|
||||||
|
private System.Windows.Forms.Panel pnl_TopBar;
|
||||||
|
private System.Windows.Forms.Panel pnl_TopBarRight;
|
||||||
|
private System.Windows.Forms.Label lbl_SystemTitle;
|
||||||
|
private System.Windows.Forms.Label lbl_DateTime;
|
||||||
|
private System.Windows.Forms.Label lbl_UserName;
|
||||||
|
private System.Windows.Forms.Panel pnl_SqlIndicator;
|
||||||
|
private System.Windows.Forms.Label lbl_SqlStatus;
|
||||||
|
|
||||||
|
// ── Sidebar ──
|
||||||
|
private System.Windows.Forms.Panel pnl_Sidebar;
|
||||||
|
private System.Windows.Forms.Panel pnl_SidebarScroll;
|
||||||
|
private System.Windows.Forms.Panel pnl_NavWeighing;
|
||||||
|
private System.Windows.Forms.Label lbl_NavWeighing;
|
||||||
|
private System.Windows.Forms.Panel pnl_NavUserMgmt;
|
||||||
|
private System.Windows.Forms.Label lbl_NavUserMgmt;
|
||||||
|
private System.Windows.Forms.Panel pnl_NavWorkpiece;
|
||||||
|
private System.Windows.Forms.Label lbl_NavWorkpiece;
|
||||||
|
private System.Windows.Forms.Panel pnl_NavTool;
|
||||||
|
private System.Windows.Forms.Label lbl_NavTool;
|
||||||
|
private System.Windows.Forms.Panel pnl_NavReport;
|
||||||
|
private System.Windows.Forms.Label lbl_NavReport;
|
||||||
|
private System.Windows.Forms.Panel pnl_NavStation;
|
||||||
|
private System.Windows.Forms.Label lbl_NavStation;
|
||||||
|
private System.Windows.Forms.Panel pnl_NavStatistics;
|
||||||
|
private System.Windows.Forms.Label lbl_NavStatistics;
|
||||||
|
private System.Windows.Forms.Panel pnl_NavSettings;
|
||||||
|
private System.Windows.Forms.Label lbl_NavSettings;
|
||||||
|
private System.Windows.Forms.Panel pnl_NavLog;
|
||||||
|
private System.Windows.Forms.Label lbl_NavLog;
|
||||||
|
private System.Windows.Forms.Panel pnl_NavPLC;
|
||||||
|
private System.Windows.Forms.Label lbl_NavPLC;
|
||||||
|
private System.Windows.Forms.Panel pnl_NavFullscreen;
|
||||||
|
private System.Windows.Forms.Label lbl_NavFullscreen;
|
||||||
|
private System.Windows.Forms.Panel pnl_NavClose;
|
||||||
|
private System.Windows.Forms.Label lbl_NavClose;
|
||||||
|
private System.Windows.Forms.Panel pnl_NavActiveIndicator;
|
||||||
|
|
||||||
|
// ── Alarm Bar ──
|
||||||
|
private System.Windows.Forms.Panel panel_Alarm;
|
||||||
|
private System.Windows.Forms.Label label_Alarm;
|
||||||
|
private System.Windows.Forms.Label lbl_AlarmIcon;
|
||||||
|
|
||||||
|
// ── Content ──
|
||||||
|
private System.Windows.Forms.Panel pnl_Content;
|
||||||
|
}
|
||||||
|
}
|
||||||
322
SCADA/MAIN_PAGE.cs
Normal file
322
SCADA/MAIN_PAGE.cs
Normal file
@@ -0,0 +1,322 @@
|
|||||||
|
namespace MesWork
|
||||||
|
{
|
||||||
|
using DC_A95;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 主窗体 - 称重数据采集分析管理系统
|
||||||
|
/// </summary>
|
||||||
|
public partial class MesWorkForm
|
||||||
|
{
|
||||||
|
public static int Curr_AID = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前活跃的导航Panel
|
||||||
|
/// </summary>
|
||||||
|
private Panel _activeNavPanel = null;
|
||||||
|
|
||||||
|
public MesWorkForm()
|
||||||
|
{
|
||||||
|
Frm_Login frm_Login = new Frm_Login();
|
||||||
|
if (frm_Login.ShowDialog() == DialogResult.OK)
|
||||||
|
{
|
||||||
|
OnStart();
|
||||||
|
|
||||||
|
InitializeComponent();
|
||||||
|
CheckForIllegalCrossThreadCalls = false;
|
||||||
|
IsMdiContainer = false;
|
||||||
|
|
||||||
|
// 加载窗口图标
|
||||||
|
LoadWindowIcon();
|
||||||
|
|
||||||
|
// 设置用户名
|
||||||
|
lbl_UserName.Text = $"操作员:{MesWorkForm.Curr_UserName}";
|
||||||
|
|
||||||
|
// 标题追加工位号
|
||||||
|
if (!string.IsNullOrEmpty(Curr_Station))
|
||||||
|
Text = $"称重数据采集分析管理系统 - {Curr_Station}";
|
||||||
|
|
||||||
|
// 启动定时器
|
||||||
|
timer_OnLine_Show.Interval = 1000;
|
||||||
|
timer_OnLine_Show.Enabled = true;
|
||||||
|
timer_Clock.Interval = 1000;
|
||||||
|
timer_Clock.Enabled = true;
|
||||||
|
|
||||||
|
// 启动SQL在线检测
|
||||||
|
CommunicationCheckOnLine();
|
||||||
|
|
||||||
|
// 初始化扫码枪
|
||||||
|
if (MesWorkForm.IsUseBarcode == 1)
|
||||||
|
{
|
||||||
|
BarcodeManager.Init();
|
||||||
|
BarcodeManager.OnBarcodeScanned = (opName, barcode) =>
|
||||||
|
{
|
||||||
|
// 在线程池中执行业务处理(与PLC信号处理一致)
|
||||||
|
System.Threading.ThreadPool.QueueUserWorkItem(_ =>
|
||||||
|
{
|
||||||
|
try { Barcode_HandleScan(opName, barcode); }
|
||||||
|
catch { }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认选中"称重作业"
|
||||||
|
SetActiveNav(pnl_NavWeighing);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Process.GetCurrentProcess().Kill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// 导航系统
|
||||||
|
// ====================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 统一导航点击事件
|
||||||
|
/// </summary>
|
||||||
|
private void Nav_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
// 获取真正的导航Panel(可能点的是Label子控件)
|
||||||
|
Panel navPanel;
|
||||||
|
if (sender is Label lbl)
|
||||||
|
navPanel = lbl.Parent as Panel;
|
||||||
|
else
|
||||||
|
navPanel = sender as Panel;
|
||||||
|
|
||||||
|
if (navPanel == null) return;
|
||||||
|
|
||||||
|
string navTag = navPanel.Tag?.ToString() ?? "";
|
||||||
|
|
||||||
|
// 退出按钮特殊处理
|
||||||
|
if (navTag.Contains("退出"))
|
||||||
|
{
|
||||||
|
DoClose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PLC监控特殊处理(弹出独立窗口)
|
||||||
|
if (navTag.Contains("PLC"))
|
||||||
|
{
|
||||||
|
new OpcForm(IsDemoMesServer).Show(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 日志查询 — 内嵌页面
|
||||||
|
if (navTag.Contains("日志"))
|
||||||
|
{
|
||||||
|
SetActiveNav(navPanel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换选中状态和内容
|
||||||
|
SetActiveNav(navPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置当前选中的导航项,高亮+加载对应内容
|
||||||
|
/// </summary>
|
||||||
|
private void SetActiveNav(Panel navPanel)
|
||||||
|
{
|
||||||
|
// 还原之前的选中项
|
||||||
|
if (_activeNavPanel != null)
|
||||||
|
{
|
||||||
|
_activeNavPanel.BackColor = Color.FromArgb(30, 58, 95);
|
||||||
|
foreach (Control c in _activeNavPanel.Controls)
|
||||||
|
if (c is Label l) l.ForeColor = Color.FromArgb(148, 163, 184);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 高亮新选中项
|
||||||
|
_activeNavPanel = navPanel;
|
||||||
|
_activeNavPanel.BackColor = Color.FromArgb(42, 74, 111);
|
||||||
|
foreach (Control c in _activeNavPanel.Controls)
|
||||||
|
if (c is Label l) l.ForeColor = Color.White;
|
||||||
|
|
||||||
|
// 移动Active指示条
|
||||||
|
pnl_NavActiveIndicator.Top = navPanel.Top;
|
||||||
|
pnl_NavActiveIndicator.Visible = true;
|
||||||
|
|
||||||
|
// 加载对应内容
|
||||||
|
LoadContentByNav(navPanel.Tag?.ToString() ?? "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 页面实例缓存(避免重复创建,保持页面状态)
|
||||||
|
/// </summary>
|
||||||
|
private readonly System.Collections.Generic.Dictionary<string, UserControl> _pageCache
|
||||||
|
= new System.Collections.Generic.Dictionary<string, UserControl>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据导航Tag加载对应的UserControl
|
||||||
|
/// </summary>
|
||||||
|
private void LoadContentByNav(string navTag)
|
||||||
|
{
|
||||||
|
pnl_Content.Controls.Clear();
|
||||||
|
|
||||||
|
string pageKey = "";
|
||||||
|
UserControl uc = null;
|
||||||
|
|
||||||
|
if (navTag.Contains("称重"))
|
||||||
|
{
|
||||||
|
pageKey = "weighing";
|
||||||
|
if (!_pageCache.ContainsKey(pageKey))
|
||||||
|
{
|
||||||
|
var wp = new Pages.UC_Weighing();
|
||||||
|
_pageCache[pageKey] = wp;
|
||||||
|
MesWorkForm.WeighingPage = wp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (navTag.Contains("用户"))
|
||||||
|
{
|
||||||
|
pageKey = "user";
|
||||||
|
if (!_pageCache.ContainsKey(pageKey))
|
||||||
|
_pageCache[pageKey] = new Pages.UC_UserMgmt();
|
||||||
|
}
|
||||||
|
else if (navTag.Contains("工件"))
|
||||||
|
{
|
||||||
|
pageKey = "workpiece";
|
||||||
|
if (!_pageCache.ContainsKey(pageKey))
|
||||||
|
_pageCache[pageKey] = new Pages.UC_WorkpieceMgmt();
|
||||||
|
}
|
||||||
|
else if (navTag.Contains("工具"))
|
||||||
|
{
|
||||||
|
pageKey = "tool";
|
||||||
|
if (!_pageCache.ContainsKey(pageKey))
|
||||||
|
_pageCache[pageKey] = new Pages.UC_ToolMgmt();
|
||||||
|
}
|
||||||
|
else if (navTag.Contains("报告"))
|
||||||
|
{
|
||||||
|
pageKey = "report";
|
||||||
|
if (!_pageCache.ContainsKey(pageKey))
|
||||||
|
_pageCache[pageKey] = new Pages.UC_Report();
|
||||||
|
}
|
||||||
|
else if (navTag.Contains("过站"))
|
||||||
|
{
|
||||||
|
pageKey = "station";
|
||||||
|
if (!_pageCache.ContainsKey(pageKey))
|
||||||
|
_pageCache[pageKey] = new Pages.UC_StationRecord();
|
||||||
|
}
|
||||||
|
else if (navTag.Contains("统计"))
|
||||||
|
{
|
||||||
|
pageKey = "statistics";
|
||||||
|
if (!_pageCache.ContainsKey(pageKey))
|
||||||
|
_pageCache[pageKey] = new Pages.UC_Statistics();
|
||||||
|
}
|
||||||
|
else if (navTag.Contains("设置"))
|
||||||
|
{
|
||||||
|
pageKey = "settings";
|
||||||
|
if (!_pageCache.ContainsKey(pageKey))
|
||||||
|
_pageCache[pageKey] = new Pages.UC_SystemSettings();
|
||||||
|
}
|
||||||
|
else if (navTag.Contains("日志"))
|
||||||
|
{
|
||||||
|
pageKey = "log";
|
||||||
|
if (!_pageCache.ContainsKey(pageKey))
|
||||||
|
_pageCache[pageKey] = new Pages.UC_LogRecord();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(pageKey) && _pageCache.ContainsKey(pageKey))
|
||||||
|
{
|
||||||
|
uc = _pageCache[pageKey];
|
||||||
|
uc.Dock = DockStyle.Fill;
|
||||||
|
pnl_Content.Controls.Add(uc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// Timer Events
|
||||||
|
// ====================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 定时器:SQL在线状态刷新 + PLC信号灯等
|
||||||
|
/// </summary>
|
||||||
|
private void timer_OnLine_Show_Tick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
// 数据库在线状态指示(只变更指示灯颜色)
|
||||||
|
if (OnLine_Sql)
|
||||||
|
{
|
||||||
|
pnl_SqlIndicator.BackColor = Color.FromArgb(16, 185, 129); // 绿色
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pnl_SqlIndicator.BackColor = Color.FromArgb(239, 68, 68); // 红色
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 定时器:时钟刷新
|
||||||
|
/// </summary>
|
||||||
|
private void timer_Clock_Tick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
lbl_DateTime.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// 窗口事件
|
||||||
|
// ====================================================================
|
||||||
|
|
||||||
|
private void MesWorkForm_Load(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
// 主界面加载完成
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MesWorkForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||||
|
{
|
||||||
|
e.Cancel = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DoClose()
|
||||||
|
{
|
||||||
|
if (MessageBox.Show("是否确认退出程序?", "退出", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
|
||||||
|
{
|
||||||
|
timer_OnLine_Show.Enabled = false;
|
||||||
|
timer_Clock.Enabled = false;
|
||||||
|
CloseDeviceConn();
|
||||||
|
BarcodeManager.Shutdown();
|
||||||
|
|
||||||
|
B_DB_Opera.SaveLog_Request(Curr_Station, Log_Type.ZK_Login, "", Log_FromAndTo.ZK, Log_FromAndTo.ZK, $"用户[{Curr_UserName}({Curr_LoginID})]退出称重系统", out long AID);
|
||||||
|
Process.GetCurrentProcess().Kill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// 全屏切换
|
||||||
|
// ====================================================================
|
||||||
|
|
||||||
|
private void btn_ToggleFullscreen_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (this.FormBorderStyle == FormBorderStyle.None)
|
||||||
|
{
|
||||||
|
// 退出全屏 → 恢复普通最大化
|
||||||
|
this.FormBorderStyle = FormBorderStyle.Sizable;
|
||||||
|
this.WindowState = FormWindowState.Maximized;
|
||||||
|
lbl_NavFullscreen.Text = "▣\n全屏";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 进入全屏 → 覆盖整个屏幕(含任务栏)
|
||||||
|
this.FormBorderStyle = FormBorderStyle.None;
|
||||||
|
this.WindowState = FormWindowState.Normal;
|
||||||
|
this.Bounds = Screen.PrimaryScreen.Bounds;
|
||||||
|
lbl_NavFullscreen.Text = "▣\n窗口";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================================================
|
||||||
|
// 窗口图标加载
|
||||||
|
// ====================================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载窗口图标(多路径搜索 + exe回退)
|
||||||
|
/// </summary>
|
||||||
|
private void LoadWindowIcon()
|
||||||
|
{
|
||||||
|
IconHelper.ApplyIcon(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
61
SCADA/MAIN_PAGE.resx
Normal file
61
SCADA/MAIN_PAGE.resx
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?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>
|
||||||
134
SCADA/MainGuide/MW.OnStart.cs
Normal file
134
SCADA/MainGuide/MW.OnStart.cs
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
using DC_A95;
|
||||||
|
using ExternalDataSync;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using SystemFramework;
|
||||||
|
using WebApi;
|
||||||
|
|
||||||
|
namespace MesWork
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 程式启动
|
||||||
|
/// </summary>
|
||||||
|
public partial class MesWorkForm
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 从这里启动
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
protected override void OnShown(EventArgs e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnStart(params object[] o)
|
||||||
|
{
|
||||||
|
//【1】系统基本参数设定
|
||||||
|
ThreadPool.SetMaxThreads(workerThreads, completionPortThreads);
|
||||||
|
Never_Know.Hello_You_All_Never_Know = Hello_You_All_Never_Know;
|
||||||
|
|
||||||
|
// 加载信号表(按设备类型对应表展开多工位)
|
||||||
|
var (dt_Tag_Mes, dt_Device) = BuildSignalTable(BasicDataTableFile);
|
||||||
|
|
||||||
|
// 保存工位名称列表及显示名映射(供UC_Weighing标题使用)
|
||||||
|
StationOpNames = new System.Collections.Generic.List<string>();
|
||||||
|
StationDisplayNames = new System.Collections.Generic.Dictionary<string, string>(System.StringComparer.OrdinalIgnoreCase);
|
||||||
|
int stIdx = 1;
|
||||||
|
foreach (System.Data.DataRow row in dt_Device.Rows)
|
||||||
|
{
|
||||||
|
string opName = row["工位号"].ToString().Trim();
|
||||||
|
string dataSource = row["数据来源"].ToString().Trim(); // 称重位1, 称重位2
|
||||||
|
StationOpNames.Add(opName);
|
||||||
|
// 显示格式:"OP10-称重位1"
|
||||||
|
StationDisplayNames[opName] = $"{opName}-{dataSource}";
|
||||||
|
stIdx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadOPCData(dt_Tag_Mes, dt_Device, IsDemoMesServer, IsWriteMonitorLog, true, false, out string error);
|
||||||
|
if (error.Length > 0)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"加载信号产生错误,程序不能启动!!错误:{error}");
|
||||||
|
Process.GetCurrentProcess().Kill();
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.Sleep(200);
|
||||||
|
StartServer();
|
||||||
|
Thread.Sleep(200);
|
||||||
|
First_TagMonitor();
|
||||||
|
|
||||||
|
var task1 = new Thread(new ThreadStart(Loop_SelectAlarmShow));
|
||||||
|
task1.IsBackground = true;
|
||||||
|
task1.Start();
|
||||||
|
|
||||||
|
// Loop_ReadRealPageShow 已移除,PLC信号显示将在 UC_Weighing 中实现
|
||||||
|
// var task2 = new Thread(new ThreadStart(Loop_ReadRealPageShow));
|
||||||
|
// task2.IsBackground = true;
|
||||||
|
// task2.Start();
|
||||||
|
|
||||||
|
|
||||||
|
initServer = new InitServer(MesWorkForm.WebApi_Port);
|
||||||
|
|
||||||
|
B_DB_Opera.SaveLog_Request(Curr_Station, Log_Type.ZK_Login, "", Log_FromAndTo.ZK, Log_FromAndTo.ZK, $"称重系统启动成功!WebPort:[{MesWorkForm.WebApi_Port}]", out long AID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构建信号表:读取Excel模板,按「设备类型对应表」的工位配置展开
|
||||||
|
/// 每个工位独立克隆一份模板,TagID加工位号前缀(如 OP10_TAG_0000001),
|
||||||
|
/// 并填充对应的 工位号、数据来源、IP、DB
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="excelFile">信号表Excel文件路径</param>
|
||||||
|
/// <returns>(展开后的信号表, 设备类型对应表)</returns>
|
||||||
|
private static (DataTable dtTagMes, DataTable dtDevice) BuildSignalTable(string excelFile)
|
||||||
|
{
|
||||||
|
// 读取设备类型对应表(所有启用的工位)
|
||||||
|
var dtDevice = NPOITest.ExeclHelper.ExcelToDataTable(excelFile, "设备类型对应表", true)
|
||||||
|
.Select("是否启用='1'").CopyToDataTable();
|
||||||
|
|
||||||
|
// 读取 MES_基本变量原始数据 模板(取全部启用行作为模板)
|
||||||
|
var dtTemplate = NPOITest.ExeclHelper.ExcelToDataTable(excelFile, "MES_基本变量原始数据", true)
|
||||||
|
.Select("是否启用='1'").CopyToDataTable();
|
||||||
|
|
||||||
|
// 按工位数量克隆模板
|
||||||
|
var dtTagMes = dtTemplate.Clone();
|
||||||
|
foreach (DataRow devRow in dtDevice.Rows)
|
||||||
|
{
|
||||||
|
string stationNo = devRow["工位号"].ToString().Trim(); // OP10, OP20
|
||||||
|
string dataSource = devRow["数据来源"].ToString().Trim(); // 称重位1, 称重位2
|
||||||
|
string deviceIP = devRow["设备IP"].ToString().Trim(); // 192.168.0.1
|
||||||
|
string deviceDB = devRow["DB"].ToString().Trim(); // DB1310, DB1311
|
||||||
|
|
||||||
|
// 提取纯DB号 ("DB1310" → "1310",若本身是数字则保持)
|
||||||
|
//string dbNumber = deviceDB.StartsWith("DB", StringComparison.OrdinalIgnoreCase)
|
||||||
|
// ? deviceDB.Substring(2) : deviceDB;
|
||||||
|
string dbNumber = deviceDB;
|
||||||
|
|
||||||
|
foreach (DataRow tplRow in dtTemplate.Rows)
|
||||||
|
{
|
||||||
|
var newRow = dtTagMes.NewRow();
|
||||||
|
for (int c = 0; c < dtTemplate.Columns.Count; c++)
|
||||||
|
newRow[c] = tplRow[c];
|
||||||
|
|
||||||
|
// 覆盖关键字段
|
||||||
|
newRow["TagID"] = $"{stationNo}_{tplRow["TagID"].ToString().Trim()}";
|
||||||
|
newRow["工位号"] = stationNo;
|
||||||
|
newRow["数据来源"] = dataSource;
|
||||||
|
newRow["IP"] = deviceIP;
|
||||||
|
newRow["DBName"] = dbNumber;
|
||||||
|
|
||||||
|
dtTagMes.Rows.Add(newRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (dtTagMes, dtDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
42
SCADA/MainGuide/MW.PageDelayRefresh.cs
Normal file
42
SCADA/MainGuide/MW.PageDelayRefresh.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace MesWork
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public partial class Temp { }
|
||||||
|
/// <summary>
|
||||||
|
/// 延时刷新(框架通用方法)
|
||||||
|
/// </summary>
|
||||||
|
public partial class MesWorkForm
|
||||||
|
{
|
||||||
|
// timer_OnLine_Show_Tick 已移至 MAIN_PAGE.cs 中统一管理
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 值处理函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool ValueT(string value)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
if (value == "true" | value == "1")
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
184
SCADA/Pages/CrudHelper.cs
Normal file
184
SCADA/Pages/CrudHelper.cs
Normal 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
177
SCADA/Pages/PagerBar.cs
Normal 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
262
SCADA/Pages/UC_LogRecord.Designer.cs
generated
Normal 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
209
SCADA/Pages/UC_LogRecord.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
120
SCADA/Pages/UC_LogRecord.resx
Normal file
120
SCADA/Pages/UC_LogRecord.resx
Normal 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
207
SCADA/Pages/UC_Report.Designer.cs
generated
Normal 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
153
SCADA/Pages/UC_Report.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
SCADA/Pages/UC_Report.resx
Normal file
20
SCADA/Pages/UC_Report.resx
Normal 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
186
SCADA/Pages/UC_StationRecord.Designer.cs
generated
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
140
SCADA/Pages/UC_StationRecord.cs
Normal file
140
SCADA/Pages/UC_StationRecord.cs
Normal 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
310
SCADA/Pages/UC_Statistics.Designer.cs
generated
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
471
SCADA/Pages/UC_Statistics.cs
Normal file
471
SCADA/Pages/UC_Statistics.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
SCADA/Pages/UC_Statistics.resx
Normal file
20
SCADA/Pages/UC_Statistics.resx
Normal 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>
|
||||||
93
SCADA/Pages/UC_SystemSettings.Designer.cs
generated
Normal file
93
SCADA/Pages/UC_SystemSettings.Designer.cs
generated
Normal 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;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
238
SCADA/Pages/UC_SystemSettings.cs
Normal file
238
SCADA/Pages/UC_SystemSettings.cs
Normal 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
253
SCADA/Pages/UC_ToolMgmt.Designer.cs
generated
Normal 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
159
SCADA/Pages/UC_ToolMgmt.cs
Normal 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(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user