初版的功能
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
|
||||
<appSettings>
|
||||
<add key="connecting1" value="Data Source=192.168.40.2;user instance=false;Initial Catalog=DissColorMachine;User ID=sa;Password=ABCabc123" />
|
||||
<add key="connecting" value="Data Source=CT-PC;user instance=false;Initial Catalog=FATrace;TrustServerCertificate=True;User ID=sa;Password=12345678" />
|
||||
<add key="connecting" value="Data Source=CT-PC;user instance=false;Initial Catalog=FATrace;TrustServerCertificate=True;User ID=admin;Password=Glico@admin" />
|
||||
<add key="connecting" value="Data Source=CT-PC;user instance=false;Initial Catalog=FATrace;TrustServerCertificate=True;User ID=admin;Password=Glico@admin" />
|
||||
<add key="RemoteConnecting" value="Data Source=CT-PC;user instance=false;Initial Catalog=MoviconDb;User ID=sa;Password=12345678" />
|
||||
<add key="PLCIP" value="127.0.0.1" />
|
||||
<add key="PLCPort" value="6000" />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0-windows10.0.19041</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
using FATrace.App.UniCodeToZPL;
|
||||
using FATrace.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Zebra.Sdk.Comm;
|
||||
using Zebra.Sdk.Printer;
|
||||
|
||||
|
||||
1
FATrace.App/frmMain.Designer.cs
generated
1
FATrace.App/frmMain.Designer.cs
generated
@@ -924,6 +924,7 @@ namespace FATrace.App
|
||||
Name = "frmMain";
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
Text = "管理界面";
|
||||
WindowState = FormWindowState.Maximized;
|
||||
Load += frmMain_Load;
|
||||
statusStrip1.ResumeLayout(false);
|
||||
statusStrip1.PerformLayout();
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
using FATrace.App.Model;
|
||||
using FATrace.Model;
|
||||
using NLog;
|
||||
using System.Net.Sockets;
|
||||
using System.Net.NetworkInformation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using static System.Runtime.CompilerServices.RuntimeHelpers;
|
||||
|
||||
namespace FATrace.App
|
||||
{
|
||||
@@ -45,7 +36,7 @@ namespace FATrace.App
|
||||
private TScalTcp? _scaleTcp;
|
||||
|
||||
// 打印机连接参数(用于状态检测)
|
||||
private string _printerIp = "192.168.0.40";
|
||||
private string _printerIp = "192.0.1.21";
|
||||
private int _printerPort = 9100;
|
||||
|
||||
// 状态缓存,避免频繁重复写日志
|
||||
|
||||
29
FATrace.Model/LineTempCode.cs
Normal file
29
FATrace.Model/LineTempCode.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
|
||||
namespace FATrace.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 产线临时条码数据
|
||||
/// </summary>
|
||||
[Table(Name = "LineTempCode")]
|
||||
public class LineTempCode
|
||||
{
|
||||
/// <summary>
|
||||
/// 主键
|
||||
/// </summary>
|
||||
[Column(IsPrimary = true, IsIdentity = true)]
|
||||
public long Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编号
|
||||
/// </summary>
|
||||
[Column(Name = "Code", IsNullable = false, StringLength = 100)]
|
||||
public string? Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
[Column(ServerTime = DateTimeKind.Local, CanUpdate = true)]
|
||||
public DateTime CreateTime { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -81,6 +81,12 @@ namespace FATrace.Model
|
||||
[Column(Name = "WeightTime")]
|
||||
public DateTime WeightTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 称重扫码时间
|
||||
/// </summary>
|
||||
[Column(Name = "WeightScanTime")]
|
||||
public DateTime WeightScanTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作者
|
||||
/// </summary>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
|
||||
<appSettings>
|
||||
<add key="connecting1" value="Data Source=192.168.40.2;user instance=false;Initial Catalog=DissColorMachine;User ID=sa;Password=ABCabc123" />
|
||||
<add key="connecting" value="Data Source=CT-PC;user instance=false;Initial Catalog=FATrace;TrustServerCertificate=True;User ID=sa;Password=12345678" />
|
||||
<add key="connecting" value="Data Source=192.0.1.100;user instance=false;Initial Catalog=FATrace;TrustServerCertificate=True;User ID=sa;Password=Glico@123" />
|
||||
<add key="RemoteConnecting" value="Data Source=CT-PC;user instance=false;Initial Catalog=MoviconDb;User ID=sa;Password=12345678" />
|
||||
<add key="PLCIP" value="127.0.0.1" />
|
||||
<add key="PLCPort" value="6000" />
|
||||
<add key="PLCIP" value="192.0.1.10" />
|
||||
<add key="PLCPort" value="5000" />
|
||||
<add key="PLCScan" value="600" />
|
||||
<!-- Keyence 布尔量地址:用于 WeightPhotoEnable 信号(默认 M100) -->
|
||||
<add key="Addr_WeightPhotoEnable" value="M100" />
|
||||
</appSettings>
|
||||
|
||||
</configuration>
|
||||
@@ -44,7 +44,7 @@ namespace FATrace.WPLApp
|
||||
//System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("zh-CN");
|
||||
|
||||
// 授权 a717c797-59e3-48de-b6b4-574a4e03dc79
|
||||
if (!HslCommunication.Authorization.SetAuthorizationCode("b23b00e2-ce46-4bfc-b33c-71c47c2c11c2"))
|
||||
if (!HslCommunication.Authorization.SetAuthorizationCode("c04165f1-2578-4d86-ab08-a293b7552a5f"))
|
||||
{
|
||||
//active failed
|
||||
MessageBox.Show("授权失败!当前程序只能使用8小时!");
|
||||
@@ -114,6 +114,7 @@ namespace FATrace.WPLApp
|
||||
{
|
||||
var fsql = Container.Resolve<IFreeSql>();
|
||||
var sysRun = Container.Resolve<SysRunService>();
|
||||
var DataServices = Container.Resolve<DataServices>();
|
||||
LogService.Info("Background services initialized");
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -197,9 +198,11 @@ namespace FATrace.WPLApp
|
||||
//containerRegistry.RegisterSingleton<TankService>();
|
||||
//containerRegistry.RegisterSingleton<MachineRtDataService>();
|
||||
|
||||
containerRegistry.RegisterSingleton<DataServices>();
|
||||
containerRegistry.RegisterSingleton<NavigationServices>();
|
||||
|
||||
|
||||
|
||||
//// 注册 Quartz 配置选项
|
||||
//containerRegistry.RegisterInstance<IOptions<QuartzOptions>>(
|
||||
// Options.Create(new QuartzOptions()) // 使用默认配置
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Configuration;
|
||||
|
||||
namespace FATrace.WPLApp
|
||||
{
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UseWPF>true</UseWPF>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Assets\Fonts\iconfont.ttf" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Assets\Fonts\iconfont.ttf">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\FATrace.Com\FATrace.Com.csproj" />
|
||||
<ProjectReference Include="..\FATrace.Model\FATrace.Model.csproj" />
|
||||
@@ -53,7 +63,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Assets\Fonts\iconfont.ttf">
|
||||
<None Include="NLog.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
105
FATrace.WPLApp/Models/LineSglModel.cs
Normal file
105
FATrace.WPLApp/Models/LineSglModel.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FATrace.WPLApp.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 产线信号模型
|
||||
/// </summary>
|
||||
public class LineSglModel : BindableBase
|
||||
{
|
||||
public LineSglModel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 称重扫码信号准备OK信号
|
||||
/// 开始获取拍照数据,并检验数据
|
||||
/// </summary>
|
||||
public event EventHandler<string> WeightScanCodeHandle; //产线信号改变
|
||||
|
||||
/// <summary>
|
||||
/// 外箱喷码Handle请求信号
|
||||
/// </summary>
|
||||
public event EventHandler<string> BoxSprayCodeReqHandle;
|
||||
|
||||
/// <summary>
|
||||
/// 外箱扫码Handle信号
|
||||
/// </summary>
|
||||
public event EventHandler<string> BoxScanCodeReqHandle;
|
||||
|
||||
private Int16 _WeightScanCodeEnable;
|
||||
/// <summary>
|
||||
/// 称重的拍照信号
|
||||
/// 开始获取拍照数据,并检验数据
|
||||
/// </summary>
|
||||
public Int16 WeightScanCodeEnable
|
||||
{
|
||||
get { return _WeightScanCodeEnable; }
|
||||
set
|
||||
{
|
||||
if (_WeightScanCodeEnable != value)
|
||||
{
|
||||
if (value == 1) WeightScanCodeHandle.Invoke(this, "WeightScanCodeHandle");
|
||||
_WeightScanCodeEnable = value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private Int16 _BoxSprayCodeReqEnable;
|
||||
/// <summary>
|
||||
/// 外箱喷码请求新信号
|
||||
/// 给PLC数据喷码数据
|
||||
/// </summary>
|
||||
public Int16 BoxSprayCodeReqEnable
|
||||
{
|
||||
get { return _BoxSprayCodeReqEnable; }
|
||||
set
|
||||
{
|
||||
if (_BoxSprayCodeReqEnable != value)
|
||||
{
|
||||
if (value == 1) BoxSprayCodeReqHandle.Invoke(this, "BoxSprayCodeReqEnable");//外箱喷码请求信号
|
||||
|
||||
_BoxSprayCodeReqEnable = value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private Int16 _BoxScanCodeEnable;
|
||||
/// <summary>
|
||||
/// 外箱扫码信号
|
||||
/// 开始获取扫码数据
|
||||
/// </summary>
|
||||
public Int16 BoxScanCodeEnable
|
||||
{
|
||||
get { return _BoxScanCodeEnable; }
|
||||
set
|
||||
{
|
||||
if (_BoxScanCodeEnable != value)
|
||||
{
|
||||
if (value==1) BoxScanCodeReqHandle.Invoke(this, "BoxScanCodeEnable"); //外箱扫码信号
|
||||
_BoxScanCodeEnable = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
52
FATrace.WPLApp/NLog.config
Normal file
52
FATrace.WPLApp/NLog.config
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
autoReload="true"
|
||||
throwConfigExceptions="true"
|
||||
internalLogLevel="Warn"
|
||||
internalLogFile="${basedir}/logs/internal-nlog.log">
|
||||
|
||||
<!-- 全局参数 -->
|
||||
<variable name="logDir" value="${basedir}/logs" />
|
||||
<variable name="layout" value="${longdate}|${level:uppercase=true}|${logger}|${threadid}|${message}${onexception:inner=|${exception:format=tostring}}" />
|
||||
|
||||
<targets>
|
||||
<!-- 调试器输出(调试时可见) -->
|
||||
<target xsi:type="Debugger" name="debugger" layout="${layout}" />
|
||||
|
||||
<!-- 常规滚动文件:按日期分割,超过大小归档,保留30天 -->
|
||||
<target xsi:type="File" name="allfile"
|
||||
fileName="${logDir}/${shortdate}.log"
|
||||
archiveFileName="${logDir}/archive/${shortdate}.{#}.log"
|
||||
archiveNumbering="Sequence"
|
||||
archiveAboveSize="10485760"
|
||||
maxArchiveFiles="30"
|
||||
concurrentWrites="true"
|
||||
keepFileOpen="false"
|
||||
encoding="utf-8"
|
||||
layout="${layout}" />
|
||||
|
||||
<!-- 错误与致命日志单独文件 -->
|
||||
<target xsi:type="File" name="errorfile"
|
||||
fileName="${logDir}/${shortdate}_error.log"
|
||||
archiveFileName="${logDir}/archive/${shortdate}_error.{#}.log"
|
||||
archiveNumbering="Sequence"
|
||||
archiveAboveSize="10485760"
|
||||
maxArchiveFiles="60"
|
||||
concurrentWrites="true"
|
||||
keepFileOpen="false"
|
||||
encoding="utf-8"
|
||||
layout="${layout}" />
|
||||
</targets>
|
||||
|
||||
<rules>
|
||||
<!-- 调试器输出:所有级别 -->
|
||||
<logger name="*" minlevel="Debug" writeTo="debugger" />
|
||||
|
||||
<!-- 常规文件:记录 Debug/Info/Warn/Error/Fatal 全部 -->
|
||||
<logger name="*" minlevel="Debug" writeTo="allfile" />
|
||||
|
||||
<!-- 错误文件:仅记录 Error/Fatal -->
|
||||
<logger name="*" minlevel="Error" writeTo="errorfile" />
|
||||
</rules>
|
||||
</nlog>
|
||||
20
FATrace.WPLApp/Services/CsvServices.cs
Normal file
20
FATrace.WPLApp/Services/CsvServices.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FATrace.WPLApp.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// CSV服务
|
||||
///导出CSV文件
|
||||
/// </summary>
|
||||
public class CsvServices
|
||||
{
|
||||
public CsvServices()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using FATrace.Model;
|
||||
using FATrace.WPLApp.Models;
|
||||
using HslCommunication;
|
||||
using HslCommunication.Profinet.Keyence;
|
||||
using Prism.Mvvm;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Windows;
|
||||
using ComConfigHelper = FATrace.Com.ConfigHelper;
|
||||
|
||||
namespace FATrace.WPLApp.Services
|
||||
{
|
||||
@@ -10,8 +13,542 @@ namespace FATrace.WPLApp.Services
|
||||
/// 数据服务
|
||||
/// 产线PLC数据交互的服务
|
||||
/// </summary>
|
||||
public class DataServices
|
||||
public class DataServices : BindableBase, IDisposable
|
||||
{
|
||||
public DataServices(ILogService logService, IFreeSql freeSql)
|
||||
{
|
||||
LogService = logService;
|
||||
FreeSql = freeSql;
|
||||
|
||||
LineSglModel = new LineSglModel();
|
||||
LineSglModel.WeightScanCodeHandle += LineSglModel_WeightScanCodeHandle;
|
||||
LineSglModel.BoxSprayCodeReqHandle += LineSglModel_BoxSprayCodeReqHandle;
|
||||
LineSglModel.BoxScanCodeReqHandle += LineSglModel_BoxScanCodeReqHandle;
|
||||
|
||||
PLCLinkInitial();
|
||||
StartPlcScan();
|
||||
//var DD= RevData("DYG05030013,20250923,802,3,01,0001,");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///外箱喷码请求
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void LineSglModel_BoxSprayCodeReqHandle(object? sender, string e)
|
||||
{
|
||||
//首先复位PLC信号
|
||||
KeyencePlcMcNet!.Write("D1100", (Int16)0);
|
||||
|
||||
//获取箱子喷码的数据+A
|
||||
var ReqData = FreeSql.Select<LineTempCode>()
|
||||
.OrderBy(a => a.Id)
|
||||
.Limit(1)
|
||||
.ToList();
|
||||
if (ReqData.Count > 0)
|
||||
{
|
||||
var CodeItem = ReqData.FirstOrDefault();
|
||||
KeyencePlcMcNet.Write("D1150", RevData(CodeItem!.Code + ",A"));
|
||||
|
||||
Console.WriteLine($"外箱喷码:{CodeItem.Code}-发送OK");
|
||||
|
||||
//这里需要删除数据吗?还是等扫码后删除,会不会过来新的箱子
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//不存在请求的数据,报错
|
||||
KeyencePlcMcNet.Write("D1102", (Int16)1);
|
||||
Console.WriteLine($"外箱喷码:不存在请求的数据");
|
||||
}
|
||||
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(1000).ConfigureAwait(false);
|
||||
KeyencePlcMcNet!.Write("D1102", (Int16)0);
|
||||
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 箱子扫描码请求
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
private void LineSglModel_BoxScanCodeReqHandle(object? sender, string e)
|
||||
{
|
||||
//首先复位PLC信号
|
||||
KeyencePlcMcNet!.Write("D1200", (Int16)0);
|
||||
|
||||
if (!string.IsNullOrEmpty(BoxScanCode))
|
||||
{
|
||||
//var IsExist = FreeSql.Select<RawProUse>().Where(a => a.BoxCode == BoxScanCode);
|
||||
var IsExist = FreeSql.Select<RawProUse>().Where(a => a.BoxCode!.Contains(BoxScanCode));// 内包和外包一样的条码测试用 ???????????????
|
||||
if (IsExist.Count() > 0)
|
||||
{
|
||||
//存在条码数据 OK,返回PLC结果
|
||||
KeyencePlcMcNet!.Write("D1210", (Int16)1);
|
||||
|
||||
Console.WriteLine($"外箱扫描码:{BoxScanCode}-存在找到");
|
||||
//// 加入队列
|
||||
//EnqueueMessage(WeightScanCode);
|
||||
LogService.Info($"外箱扫描码:{BoxScanCode}");
|
||||
|
||||
//删除临时的队列条码数据
|
||||
var DeleteResult = FreeSql.Delete<LineTempCode>()
|
||||
.Where(p => BoxScanCode.Contains(p.Code!))
|
||||
.ExecuteAffrows();
|
||||
if (DeleteResult > 0)
|
||||
{
|
||||
Console.WriteLine($"外箱扫描码:{WeightScanCode}-删除临时队列数据成功");
|
||||
LogService.Info($"外箱扫描码:{WeightScanCode}-删除临时队列数据成功");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"外箱扫描码:{WeightScanCode}-删除临时队列数据失败");
|
||||
LogService.Info($"外箱扫描码:{WeightScanCode}-删除临时队列数据失败");
|
||||
}
|
||||
|
||||
var Result = FreeSql.Update<RawProUse>()
|
||||
.Set(p => p.OutTime, DateTime.Now)
|
||||
.Where(p => p.BoxCode == BoxScanCode+",A")//外箱二维码就是外箱扫描码
|
||||
.ExecuteAffrows();
|
||||
if (Result > 0)
|
||||
{
|
||||
Console.WriteLine($"外箱扫描码:{WeightScanCode}更新时间成功");
|
||||
LogService.Info($"外箱扫描码:{WeightScanCode}更新时间成功");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"外箱扫描码:{WeightScanCode}更新时间失败");
|
||||
LogService.Warn($"外箱扫描码:{WeightScanCode}更新时间失败");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//不存在条码数据 NG,返回PLC结果报警
|
||||
KeyencePlcMcNet!.Write("D1210", (Int16)2);
|
||||
|
||||
Console.WriteLine($"外箱扫描码:{WeightScanCode}-未发现外箱扫码数据在数据库中");
|
||||
LogService.Warn($"外箱扫描码:{WeightScanCode}-未发现外箱扫码数据在数据库中");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"外箱扫描码为空");
|
||||
LogService.Warn("外箱扫描码为空");
|
||||
}
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(1000).ConfigureAwait(false);
|
||||
KeyencePlcMcNet!.Write("D1210", (Int16)0);
|
||||
|
||||
KeyencePlcMcNet.Write("D1250", new Int16[30]);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 称重扫描码请求数据
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
private void LineSglModel_WeightScanCodeHandle(object? sender, string e)
|
||||
{
|
||||
//首先复位PLC信号
|
||||
KeyencePlcMcNet!.Write("D1000", (Int16)0);
|
||||
|
||||
if (!string.IsNullOrEmpty(WeightScanCode))
|
||||
{
|
||||
var IsExist = FreeSql.Select<RawProUse>().Where(a => a.InBagCode == WeightScanCode);
|
||||
if (IsExist.Count() > 0)
|
||||
{
|
||||
//存在条码数据 OK,返回PLC结果
|
||||
KeyencePlcMcNet!.Write("D1010", (Int16)1);
|
||||
|
||||
Console.WriteLine($"称重扫描码:{WeightScanCode}");
|
||||
//// 加入队列
|
||||
//EnqueueMessage(WeightScanCode);
|
||||
LogService.Info($"称重扫描码:{WeightScanCode}");
|
||||
|
||||
var TempData = FreeSql.Insert<LineTempCode>(new LineTempCode()
|
||||
{
|
||||
Code = WeightScanCode
|
||||
}).ExecuteAffrows();
|
||||
|
||||
var Result = FreeSql.Update<RawProUse>()
|
||||
.Set(p => p.WeightScanTime, DateTime.Now)
|
||||
.Where(p => p.InBagCode == WeightScanCode)//内箱二维码就是称重扫描码
|
||||
.ExecuteAffrows();
|
||||
if (Result > 0)
|
||||
{
|
||||
Console.WriteLine($"称重扫描码:{WeightScanCode}更新时间成功");
|
||||
LogService.Info($"称重扫描码:{WeightScanCode}更新时间成功");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"称重扫描码:{WeightScanCode}更新时间失败");
|
||||
LogService.Warn($"称重扫描码:{WeightScanCode}更新时间失败");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//不存在条码数据 NG,返回PLC结果报警
|
||||
KeyencePlcMcNet!.Write("D1010", (Int16)2);
|
||||
|
||||
Console.WriteLine($"称重扫描码:{WeightScanCode}-未发现内包扫码数据在数据库中");
|
||||
LogService.Warn($"称重扫描码:{WeightScanCode}-未发现内包扫码数据在数据库中");
|
||||
}
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(1000).ConfigureAwait(false);
|
||||
KeyencePlcMcNet!.Write("D1010", (Int16)0);
|
||||
|
||||
KeyencePlcMcNet.Write("D1050", new Int16[30]);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"称重扫描码为空");
|
||||
LogService.Warn("称重扫描码为空");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ILogService LogService { get; }
|
||||
public IFreeSql FreeSql { get; }
|
||||
|
||||
//通信组件
|
||||
private KeyenceMcNet KeyencePlcMcNet { get; set; } = null;
|
||||
|
||||
private string _WeightScanCode;
|
||||
/// <summary>
|
||||
/// 称重扫描码
|
||||
/// </summary>
|
||||
public string WeightScanCode
|
||||
{
|
||||
get { return _WeightScanCode; }
|
||||
set { _WeightScanCode = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
|
||||
private string _BoxScanCode;
|
||||
/// <summary>
|
||||
/// 外箱喷码扫码数据
|
||||
/// </summary>
|
||||
public string BoxScanCode
|
||||
{
|
||||
get { return _BoxScanCode; }
|
||||
set { _BoxScanCode = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 扫描控制
|
||||
private CancellationTokenSource? _plcScanCts;
|
||||
private Task? _plcScanTask;
|
||||
private volatile bool _isScanning = false;
|
||||
public bool IsScanning => _isScanning;
|
||||
private bool _disposed = false;
|
||||
|
||||
/// <summary>
|
||||
/// 简单字符串队列(FIFO)
|
||||
/// </summary>
|
||||
private readonly ConcurrentQueue<string> _messageQueue = new();
|
||||
|
||||
/// <summary>
|
||||
/// 入队:将字符串加入 FIFO 队列(先进先出)。允许空字符串,不允许 null。
|
||||
/// </summary>
|
||||
/// <param name="message">要加入队列的字符串</param>
|
||||
/// <exception cref="ArgumentNullException">当 message 为 null 时抛出</exception>
|
||||
public void EnqueueMessage(string message)
|
||||
{
|
||||
if (message is null) throw new ArgumentNullException(nameof(message));
|
||||
_messageQueue.Enqueue(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 出队:尝试从 FIFO 队列取出一个字符串。
|
||||
/// </summary>
|
||||
/// <param name="message">输出参数:若成功则为取出的字符串;若失败(队列为空)则为 default</param>
|
||||
/// <returns>是否成功取出</returns>
|
||||
public bool TryDequeueMessage(out string message)
|
||||
{
|
||||
return _messageQueue.TryDequeue(out message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 产线信号模型
|
||||
/// </summary>
|
||||
public LineSglModel LineSglModel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// PLC通信初始化
|
||||
/// </summary>
|
||||
/// <param name="PLCIp"></param>
|
||||
/// <param name="Port"></param>
|
||||
private void PLCLinkInitial()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 读取 PLC 配置(大小写敏感,采用公共 ConfigHelper 并提供默认值)
|
||||
string PLCIP = ComConfigHelper.GetStringOrDefault("PLCIP", "192.0.1.10");
|
||||
int Port = ComConfigHelper.GetIntOrDefault("PLCPort", 5000);
|
||||
|
||||
//PLC通信的连接
|
||||
KeyencePlcMcNet = new KeyenceMcNet();
|
||||
KeyencePlcMcNet.IpAddress = PLCIP;
|
||||
KeyencePlcMcNet.Port = Port;
|
||||
KeyencePlcMcNet.ConnectClose();
|
||||
|
||||
|
||||
KeyencePlcMcNet.ConnectTimeOut = 3000; // 连接3秒超时
|
||||
OperateResult connect = KeyencePlcMcNet.ConnectServer();
|
||||
if (connect.IsSuccess)//初始连接状态的显示判断
|
||||
{
|
||||
Console.WriteLine($"PLC-连接 OK");
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show(connect.Message + Environment.NewLine + "ErrorCode: " + connect.ErrorCode);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogService.Error(String.Format("ErrSource : {0} ErrMsg : {1}", ex.StackTrace.ToString(), ex.Message.ToString()));
|
||||
//insertLogToDBDelegate.BeginInvoke(1, "UpdateUIMethod异常", ex.Message.ToString() + ex.StackTrace.Substring(ex.StackTrace.Length - 40, 40), null, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动PLC扫描。若已在扫描则忽略重复启动。
|
||||
/// </summary>
|
||||
/// <param name="scanPeriod">扫描周期,若为 null 则读取 App.config 的 PLCScan(毫秒),默认600ms</param>
|
||||
/// <param name="externalToken">可选:外部取消令牌,用于联动取消</param>
|
||||
public void StartPlcScan(TimeSpan? scanPeriod = null, CancellationToken externalToken = default)
|
||||
{
|
||||
if (_isScanning) return;
|
||||
|
||||
var period = scanPeriod ?? ComConfigHelper.GetTimeSpanOrDefault("PLCScan", TimeSpan.FromMilliseconds(600));
|
||||
|
||||
_plcScanCts = CancellationTokenSource.CreateLinkedTokenSource(externalToken);
|
||||
var token = _plcScanCts.Token;
|
||||
_isScanning = true;
|
||||
|
||||
_plcScanTask = Task.Run(() => PlcScanLoopAsync(period, token), token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止PLC扫描,等待后台任务结束。
|
||||
/// </summary>
|
||||
public async Task StopPlcScanAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_plcScanCts != null)
|
||||
{
|
||||
_plcScanCts.Cancel();
|
||||
}
|
||||
if (_plcScanTask != null)
|
||||
{
|
||||
try { await _plcScanTask.ConfigureAwait(false); } catch { /* ignore */ }
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isScanning = false;
|
||||
_plcScanTask = null;
|
||||
_plcScanCts?.Dispose();
|
||||
_plcScanCts = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 称重扫描条码OperateResult结果
|
||||
/// </summary>
|
||||
private OperateResult<string> OperateResultWeightScanCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 称重扫描条码OK信号
|
||||
/// </summary>
|
||||
private OperateResult<Int16> OperateResultWeightScanSgl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 外箱喷码请求信号
|
||||
/// </summary>
|
||||
private OperateResult<Int16> OperateResultBoxSprayCodeReqSgl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 外箱扫码条码OperateResult结果
|
||||
/// </summary>
|
||||
private OperateResult<string> OperateResultBoxScanCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 外箱扫码请求信号
|
||||
/// </summary>
|
||||
private OperateResult<Int16> OperateResultBoxScanSgl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 扫描循环:按周期轮询PLC寄存器并更新模型。
|
||||
/// - 读取配置项 Addr_WeightPhotoEnable(默认 M100)为布尔量
|
||||
/// - 读失败时尝试重连一次
|
||||
/// </summary>
|
||||
private async Task PlcScanLoopAsync(TimeSpan period, CancellationToken token)
|
||||
{
|
||||
string addrWeight = ComConfigHelper.GetStringOrDefault("Addr_WeightPhotoEnable", "M100");
|
||||
bool? lastWeight = null;
|
||||
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (KeyencePlcMcNet == null)
|
||||
{
|
||||
PLCLinkInitial();
|
||||
}
|
||||
|
||||
//内包扫码
|
||||
OperateResultWeightScanCode = KeyencePlcMcNet!.ReadString("D1050", 20);
|
||||
if (OperateResultWeightScanCode.IsSuccess)
|
||||
{
|
||||
WeightScanCode = RevData(OperateResultWeightScanCode.Content).Replace("\r", "").Replace("\n", "");
|
||||
}
|
||||
OperateResultWeightScanSgl = KeyencePlcMcNet!.ReadInt16("D1000");
|
||||
if (OperateResultWeightScanSgl.IsSuccess)
|
||||
{
|
||||
LineSglModel.WeightScanCodeEnable = OperateResultWeightScanSgl.Content;
|
||||
}
|
||||
|
||||
//外箱喷码
|
||||
OperateResultBoxSprayCodeReqSgl = KeyencePlcMcNet!.ReadInt16("D1100");
|
||||
if (OperateResultBoxSprayCodeReqSgl.IsSuccess)
|
||||
{
|
||||
LineSglModel.BoxSprayCodeReqEnable = OperateResultBoxSprayCodeReqSgl.Content;
|
||||
}
|
||||
|
||||
//外箱扫码
|
||||
OperateResultBoxScanCode = KeyencePlcMcNet!.ReadString("D1250", 20);
|
||||
if (OperateResultBoxScanCode.IsSuccess)
|
||||
{
|
||||
BoxScanCode = RevData(OperateResultBoxScanCode.Content).Replace("\r", "").Replace("\n", "");
|
||||
}
|
||||
OperateResultBoxScanSgl = KeyencePlcMcNet!.ReadInt16("D1200");
|
||||
if (OperateResultBoxScanSgl.IsSuccess)
|
||||
{
|
||||
LineSglModel.BoxScanCodeEnable = OperateResultBoxScanSgl.Content;
|
||||
}
|
||||
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogService.Error($"PLC 扫描异常: {ex}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
await Task.Delay(period, token).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// 不允许从 finally 中 break/return,
|
||||
// 这里吞掉异常,循环将在下一次 while 判断时依据 token 自动退出
|
||||
}
|
||||
}
|
||||
}
|
||||
_isScanning = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试重连 PLC(快速一次)
|
||||
/// </summary>
|
||||
private async Task TryReconnectAsync(CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (KeyencePlcMcNet == null) { PLCLinkInitial(); return; }
|
||||
KeyencePlcMcNet.ConnectClose();
|
||||
await Task.Delay(100, token).ConfigureAwait(false);
|
||||
KeyencePlcMcNet.ConnectTimeOut = 3000;
|
||||
var ret = KeyencePlcMcNet.ConnectServer();
|
||||
if (!ret.IsSuccess)
|
||||
{
|
||||
LogService.Warn($"PLC重连失败: {ret.Message} (Code: {ret.ErrorCode})");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogService.Error($"PLC重连异常: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放资源,确保扫描停止并断开PLC连接。
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
try
|
||||
{
|
||||
// 停止扫描
|
||||
try { StopPlcScanAsync().GetAwaiter().GetResult(); } catch { }
|
||||
|
||||
// 解除事件订阅(当前未订阅自定义事件,保留占位以便后续扩展)
|
||||
// try { /* no event to unsubscribe */ } catch { }
|
||||
|
||||
// 关闭PLC连接
|
||||
try { KeyencePlcMcNet?.ConnectClose(); } catch { }
|
||||
}
|
||||
finally
|
||||
{
|
||||
KeyencePlcMcNet = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 把字符串对调
|
||||
/// </summary>
|
||||
private string RevData(string Code)
|
||||
{
|
||||
// 需求:PLC 字符串按“字”(2字节)进行高低字节对调,导致 ABCDEF -> BADCFE
|
||||
// 纠正方式:按两个字符一组交换顺序,奇数长度保留最后一个字符
|
||||
if (string.IsNullOrEmpty(Code)) return string.Empty;
|
||||
|
||||
// 去掉读取中可能包含的 '\0' 空字符
|
||||
var src = Code.Replace("\0", string.Empty);
|
||||
|
||||
var sb = new System.Text.StringBuilder(src.Length);
|
||||
for (int i = 0; i < src.Length; i += 2)
|
||||
{
|
||||
if (i + 1 < src.Length)
|
||||
{
|
||||
sb.Append(src[i + 1]);
|
||||
sb.Append(src[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 奇数长度,最后一个字符原样保留
|
||||
sb.Append(src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -12,9 +12,15 @@ namespace FATrace.WPLApp.Services
|
||||
public interface ILogService
|
||||
{
|
||||
void Debug(string msg);
|
||||
void Debug(string msg, Exception ex);
|
||||
void Error(string msg);
|
||||
void Error(string msg, Exception ex);
|
||||
void Error(Exception ex);
|
||||
void Fatal(string msg);
|
||||
void Fatal(string msg, Exception ex);
|
||||
void Info(string msg);
|
||||
void Info(string msg, Exception ex);
|
||||
void Warn(string msg);
|
||||
void Warn(string msg, Exception ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using NLog;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -12,16 +12,14 @@ namespace FATrace.WPLApp.Services
|
||||
/// </summary>
|
||||
public class LogService : ILogService
|
||||
{
|
||||
private static Logger Logger = LogManager.GetCurrentClassLogger(); //初始化日志类
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); // 初始化日志类
|
||||
|
||||
/// <summary>
|
||||
/// 调试日志
|
||||
/// </summary>
|
||||
/// <param name="msg">日志内容</param>
|
||||
public void Debug(string msg)
|
||||
{
|
||||
Logger.Debug(msg);
|
||||
}
|
||||
public void Debug(string msg) => Logger.Debug(msg);
|
||||
public void Debug(string msg, Exception ex) => Logger.Debug(ex, msg);
|
||||
|
||||
/// <summary>
|
||||
/// 信息日志
|
||||
@@ -31,10 +29,8 @@ namespace FATrace.WPLApp.Services
|
||||
/// 适用大部分场景
|
||||
/// 1.记录日志文件
|
||||
/// </remarks>
|
||||
public void Info(string msg)
|
||||
{
|
||||
Logger.Info(msg);
|
||||
}
|
||||
public void Info(string msg) => Logger.Info(msg);
|
||||
public void Info(string msg, Exception ex) => Logger.Info(ex, msg);
|
||||
|
||||
/// <summary>
|
||||
/// 错误日志
|
||||
@@ -44,10 +40,9 @@ namespace FATrace.WPLApp.Services
|
||||
/// 适用异常,错误日志记录
|
||||
/// 1.记录日志文件
|
||||
/// </remarks>
|
||||
public void Error(string msg)
|
||||
{
|
||||
Logger.Error(msg);
|
||||
}
|
||||
public void Error(string msg) => Logger.Error(msg);
|
||||
public void Error(string msg, Exception ex) => Logger.Error(ex, msg);
|
||||
public void Error(Exception ex) => Logger.Error(ex);
|
||||
|
||||
/// <summary>
|
||||
/// 严重致命错误日志
|
||||
@@ -57,10 +52,8 @@ namespace FATrace.WPLApp.Services
|
||||
/// 1.记录日志文件
|
||||
/// 2.控制台输出
|
||||
/// </remarks>
|
||||
public void Fatal(string msg)
|
||||
{
|
||||
Logger.Fatal(msg);
|
||||
}
|
||||
public void Fatal(string msg) => Logger.Fatal(msg);
|
||||
public void Fatal(string msg, Exception ex) => Logger.Fatal(ex, msg);
|
||||
|
||||
/// <summary>
|
||||
/// 警告日志
|
||||
@@ -70,13 +63,7 @@ namespace FATrace.WPLApp.Services
|
||||
/// 1.记录日志文件
|
||||
/// 2.发送日志邮件
|
||||
/// </remarks>
|
||||
public void Warn(string msg)
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.Warn(msg);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
public void Warn(string msg) => Logger.Warn(msg);
|
||||
public void Warn(string msg, Exception ex) => Logger.Warn(ex, msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,33 +26,6 @@ namespace FATrace.WPLApp.Services
|
||||
IsParent = false,
|
||||
},
|
||||
|
||||
// 工艺监控导航项(父级)
|
||||
new NavItemDto()
|
||||
{
|
||||
Name = "工艺监控",
|
||||
CmdPar = "",
|
||||
Icon = "\uea12",
|
||||
IsParent = true,
|
||||
ChildrenNavItemDtos = new ObservableCollection<NavItemDto>()
|
||||
{
|
||||
// 基础数据的子项
|
||||
new NavItemDto()
|
||||
{
|
||||
Name = "3D工艺流程",
|
||||
CmdPar = "3D工艺流程",
|
||||
Icon = "\uee12",
|
||||
IsParent = false,
|
||||
},
|
||||
new NavItemDto()
|
||||
{
|
||||
Name = "管道线路",
|
||||
CmdPar = "管道线路",
|
||||
Icon = "\ue650",
|
||||
IsParent = false,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
// 生产管理导航项(父级) - 新增测试导航
|
||||
new NavItemDto()
|
||||
{
|
||||
|
||||
@@ -23,6 +23,17 @@ namespace FATrace.WPLApp.Services
|
||||
|
||||
}
|
||||
|
||||
private bool _PlcLinkState = false;
|
||||
/// <summary>
|
||||
/// PLC连接状态
|
||||
/// </summary>
|
||||
public bool PlcLinkState
|
||||
{
|
||||
get { return _PlcLinkState; }
|
||||
set { _PlcLinkState = value;RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
|
||||
private string? _CurUser;
|
||||
/// <summary>
|
||||
/// 当前的用户
|
||||
|
||||
@@ -6,12 +6,7 @@ using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Regions;
|
||||
using Prism.Services.Dialogs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FATrace.WPLApp.ViewModels
|
||||
{
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
x:Class="FATrace.WPLApp.Views.RawProUseView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
d:DesignHeight="720"
|
||||
d:DesignWidth="1280"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="1280" d:DesignHeight="720">
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<!-- 布尔到可见性转换器,用于显示忙碌状态 -->
|
||||
<!-- 布尔到可见性转换器,用于显示忙碌状态 -->
|
||||
<BooleanToVisibilityConverter x:Key="Bool2Vis" />
|
||||
</UserControl.Resources>
|
||||
<Grid Margin="10">
|
||||
@@ -19,160 +20,284 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 查询条件区域 -->
|
||||
<Border Grid.Row="0" Padding="10" Background="#F9F9F9" BorderBrush="#DDDDDD" BorderThickness="1" CornerRadius="4">
|
||||
<!-- 查询条件区域 -->
|
||||
<Border
|
||||
Grid.Row="0"
|
||||
Padding="10"
|
||||
Background="#F9F9F9"
|
||||
BorderBrush="#DDDDDD"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*"/>
|
||||
<ColumnDefinition Width="2*"/>
|
||||
<ColumnDefinition Width="2*"/>
|
||||
<ColumnDefinition Width="2*"/>
|
||||
<ColumnDefinition Width="2*"/>
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="2*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 第一行:编码/名称/批号 -->
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0" Margin="0,0,10,8">
|
||||
<TextBlock VerticalAlignment="Center" Text="原料编号:"/>
|
||||
<TextBox Width="160" Text="{Binding RawCode, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
<!-- 第一行:编码/名称/批号 -->
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Margin="0,0,10,8"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="原料编号:" />
|
||||
<TextBox Width="160" Text="{Binding RawCode, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="1" Margin="0,0,10,8">
|
||||
<TextBlock VerticalAlignment="Center" Text="原料名称:"/>
|
||||
<TextBox Width="160" Text="{Binding RawName, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,10,8"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="原料名称:" />
|
||||
<TextBox Width="160" Text="{Binding RawName, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="2" Margin="0,0,10,8">
|
||||
<TextBlock VerticalAlignment="Center" Text="批号:"/>
|
||||
<TextBox Width="160" Text="{Binding Batch, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Grid.Column="2"
|
||||
Margin="0,0,10,8"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="批号:" />
|
||||
<TextBox Width="160" Text="{Binding Batch, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="3" Margin="0,0,10,8">
|
||||
<TextBlock VerticalAlignment="Center" Text="操作者:"/>
|
||||
<TextBox Width="140" Text="{Binding OpUser, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Grid.Column="3"
|
||||
Margin="0,0,10,8"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="操作者:" />
|
||||
<TextBox Width="140" Text="{Binding OpUser, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="4" Margin="0,0,10,8">
|
||||
<TextBlock VerticalAlignment="Center" Text="确认者:"/>
|
||||
<TextBox Width="140" Text="{Binding CheckUser, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Grid.Column="4"
|
||||
Margin="0,0,10,8"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="确认者:" />
|
||||
<TextBox Width="140" Text="{Binding CheckUser, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- 第二行:扫码条件 -->
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="0" Margin="0,0,10,8">
|
||||
<TextBlock VerticalAlignment="Center" Text="内袋二维码:"/>
|
||||
<TextBox Width="160" Text="{Binding InBagCode, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
<!-- 第二行:扫码条件 -->
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="0,0,10,8"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="内袋二维码:" />
|
||||
<TextBox Width="160" Text="{Binding InBagCode, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="1" Margin="0,0,10,8">
|
||||
<TextBlock VerticalAlignment="Center" Text="外箱二维码:"/>
|
||||
<TextBox Width="160" Text="{Binding BoxCode, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,10,8"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="外箱二维码:" />
|
||||
<TextBox Width="160" Text="{Binding BoxCode, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- 第三行:时间范围与操作按钮 -->
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="2" Grid.Column="0" Margin="0,5,10,0">
|
||||
<TextBlock VerticalAlignment="Center" Text="开始:"/>
|
||||
<DatePicker Width="160" SelectedDate="{Binding StartTime, Mode=TwoWay}"/>
|
||||
<!-- 第三行:时间范围与操作按钮 -->
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Margin="0,5,10,0"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="开始:" />
|
||||
<DatePicker Width="160" SelectedDate="{Binding StartTime, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="2" Grid.Column="1" Margin="0,5,10,0">
|
||||
<TextBlock VerticalAlignment="Center" Text="结束:"/>
|
||||
<DatePicker Width="160" SelectedDate="{Binding EndTime, Mode=TwoWay}"/>
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Margin="0,5,10,0"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="结束:" />
|
||||
<DatePicker Width="160" SelectedDate="{Binding EndTime, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="2" Grid.Column="3" Margin="0,5,10,0" HorizontalAlignment="Right">
|
||||
<Button Content="查询" Width="80" Margin="0,0,8,0" Command="{Binding SearchCommand}"/>
|
||||
<Button Content="清空" Width="80" Margin="0,0,8,0" Command="{Binding ClearCommand}"/>
|
||||
<Button Content="导出Excel" Width="100" Command="{Binding ExportCommand}"/>
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Grid.Column="3"
|
||||
Margin="0,5,10,0"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Width="80"
|
||||
Margin="0,0,8,0"
|
||||
Command="{Binding SearchCommand}"
|
||||
Content="查询" />
|
||||
<Button
|
||||
Width="80"
|
||||
Margin="0,0,8,0"
|
||||
Command="{Binding ClearCommand}"
|
||||
Content="清空" />
|
||||
<Button
|
||||
Width="100"
|
||||
Command="{Binding ExportCommand}"
|
||||
Content="导出Excel" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- 列表区域 -->
|
||||
<DataGrid Grid.Row="1" Margin="0,10,0,10"
|
||||
ItemsSource="{Binding Items}"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
IsReadOnly="True">
|
||||
<!-- 列表区域 -->
|
||||
<DataGrid
|
||||
Grid.Row="1"
|
||||
Margin="0,10,0,10"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
IsReadOnly="True"
|
||||
ItemsSource="{Binding Items}">
|
||||
<DataGrid.ColumnHeaderStyle>
|
||||
<Style TargetType="DataGridColumnHeader">
|
||||
<Setter Property="FontSize" Value="16"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
<Setter Property="FontSize" Value="16" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
</Style>
|
||||
</DataGrid.ColumnHeaderStyle>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Id" Binding="{Binding Id}" Width="80"/>
|
||||
<DataGridTextColumn Header="原料编号" Binding="{Binding RawCode}" Width="120"/>
|
||||
<DataGridTextColumn Header="原料名称" Binding="{Binding RawName}" Width="160"/>
|
||||
<DataGridTextColumn Header="内袋二维码" Binding="{Binding InBagCode}" Width="180"/>
|
||||
<DataGridTextColumn Header="外箱二维码" Binding="{Binding BoxCode}" Width="180"/>
|
||||
<DataGridTextColumn Header="批号" Binding="{Binding Batch}" Width="120"/>
|
||||
<DataGridTextColumn Header="保质期(年)" Binding="{Binding ShelfLife}" Width="100"/>
|
||||
<DataGridTextColumn Header="称重重量(g)" Binding="{Binding Weight}" Width="100"/>
|
||||
<DataGridTextColumn Header="剩余重量(g)" Binding="{Binding RemainWeight}" Width="100"/>
|
||||
<DataGridTextColumn Header="入库总重量(g)" Binding="{Binding StockWeight}" Width="120"/>
|
||||
<DataGridTextColumn Header="称重时间" Binding="{Binding WeightTime, StringFormat=yyyy-MM-dd HH:mm:ss}" Width="160"/>
|
||||
<DataGridTextColumn Header="操作者" Binding="{Binding OpUser}" Width="100"/>
|
||||
<DataGridTextColumn Header="确认者" Binding="{Binding CheckUser}" Width="150"/>
|
||||
<DataGridTextColumn Header="出库时间" Binding="{Binding OutTime, StringFormat=yyyy-MM-dd HH:mm:ss}" Width="160"/>
|
||||
<DataGridTextColumn Header="创建时间" Binding="{Binding CreateTime, StringFormat=yyyy-MM-dd HH:mm:ss}" Width="160"/>
|
||||
<DataGridTextColumn
|
||||
Width="80"
|
||||
Binding="{Binding Id}"
|
||||
Header="Id" />
|
||||
<DataGridTextColumn
|
||||
Width="120"
|
||||
Binding="{Binding RawCode}"
|
||||
Header="原料编号" />
|
||||
<DataGridTextColumn
|
||||
Width="160"
|
||||
Binding="{Binding RawName}"
|
||||
Header="原料名称" />
|
||||
<DataGridTextColumn
|
||||
Width="180"
|
||||
Binding="{Binding InBagCode}"
|
||||
Header="内袋二维码" />
|
||||
<DataGridTextColumn
|
||||
Width="180"
|
||||
Binding="{Binding BoxCode}"
|
||||
Header="外箱二维码" />
|
||||
<DataGridTextColumn
|
||||
Width="120"
|
||||
Binding="{Binding Batch}"
|
||||
Header="批号" />
|
||||
<DataGridTextColumn
|
||||
Width="100"
|
||||
Binding="{Binding ShelfLife}"
|
||||
Header="保质期(年)" />
|
||||
<DataGridTextColumn
|
||||
Width="100"
|
||||
Binding="{Binding Weight}"
|
||||
Header="称重重量(g)" />
|
||||
<DataGridTextColumn
|
||||
Width="100"
|
||||
Binding="{Binding RemainWeight}"
|
||||
Header="剩余重量(g)" />
|
||||
<DataGridTextColumn
|
||||
Width="120"
|
||||
Binding="{Binding StockWeight}"
|
||||
Header="入库总重量(g)" />
|
||||
<DataGridTextColumn
|
||||
Width="160"
|
||||
Binding="{Binding WeightTime, StringFormat=yyyy-MM-dd HH:mm:ss}"
|
||||
Header="称重时间" />
|
||||
<DataGridTextColumn
|
||||
Width="100"
|
||||
Binding="{Binding OpUser}"
|
||||
Header="操作者" />
|
||||
<DataGridTextColumn
|
||||
Width="150"
|
||||
Binding="{Binding CheckUser}"
|
||||
Header="确认者" />
|
||||
<DataGridTextColumn
|
||||
Width="160"
|
||||
Binding="{Binding OutTime, StringFormat=yyyy-MM-dd HH:mm:ss}"
|
||||
Header="出库时间" />
|
||||
<DataGridTextColumn
|
||||
Width="160"
|
||||
Binding="{Binding CreateTime, StringFormat=yyyy-MM-dd HH:mm:ss}"
|
||||
Header="创建时间" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
<!-- 状态栏 -->
|
||||
<!-- 状态栏 -->
|
||||
<StatusBar Grid.Row="2">
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="本页:"/>
|
||||
<TextBlock Text="本页:" />
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="{Binding Items.Count}"/>
|
||||
<TextBlock Text="{Binding Items.Count}" />
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<TextBlock Text=" 总数:"/>
|
||||
<TextBlock Text=" 总数:" />
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="{Binding TotalCount}"/>
|
||||
<TextBlock Text="{Binding TotalCount}" />
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<Separator Width="20"/>
|
||||
<Separator Width="20" />
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="页码:"/>
|
||||
<TextBlock Text="页码:" />
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="{Binding PageIndex}"/>
|
||||
<TextBlock Text="{Binding PageIndex}" />
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="/"/>
|
||||
<TextBlock Text="/" />
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="{Binding TotalPages}"/>
|
||||
<TextBlock Text="{Binding TotalPages}" />
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<Button Content="|<" Width="40" Margin="5,0" Command="{Binding FirstPageCommand}"/>
|
||||
<Button
|
||||
Width="40"
|
||||
Margin="5,0"
|
||||
Command="{Binding FirstPageCommand}"
|
||||
Content="|<" />
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<Button Content="<" Width="40" Margin="5,0" Command="{Binding PrevPageCommand}"/>
|
||||
<Button
|
||||
Width="40"
|
||||
Margin="5,0"
|
||||
Command="{Binding PrevPageCommand}"
|
||||
Content="<" />
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<Button Content=">" Width="40" Margin="5,0" Command="{Binding NextPageCommand}"/>
|
||||
<Button
|
||||
Width="40"
|
||||
Margin="5,0"
|
||||
Command="{Binding NextPageCommand}"
|
||||
Content=">" />
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<Button Content=">|" Width="40" Margin="5,0" Command="{Binding LastPageCommand}"/>
|
||||
<Button
|
||||
Width="40"
|
||||
Margin="5,0"
|
||||
Command="{Binding LastPageCommand}"
|
||||
Content=">|" />
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<Separator Width="20"/>
|
||||
<Separator Width="20" />
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<TextBlock Text="页大小:"/>
|
||||
<TextBlock Text="页大小:" />
|
||||
</StatusBarItem>
|
||||
<StatusBarItem>
|
||||
<ComboBox Width="80" SelectedValue="{Binding PageSize, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="Content">
|
||||
<ComboBoxItem Content="10"/>
|
||||
<ComboBoxItem Content="20"/>
|
||||
<ComboBoxItem Content="50"/>
|
||||
<ComboBoxItem Content="100"/>
|
||||
<ComboBox
|
||||
Width="80"
|
||||
SelectedValue="{Binding PageSize, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
SelectedValuePath="Content">
|
||||
<ComboBoxItem Content="10" />
|
||||
<ComboBoxItem Content="20" />
|
||||
<ComboBoxItem Content="50" />
|
||||
<ComboBoxItem Content="100" />
|
||||
</ComboBox>
|
||||
</StatusBarItem>
|
||||
<StatusBarItem HorizontalAlignment="Right">
|
||||
<TextBlock Text="正在处理..." Visibility="{Binding IsBusy, Converter={StaticResource Bool2Vis}}"/>
|
||||
<TextBlock Text="正在处理..." Visibility="{Binding IsBusy, Converter={StaticResource Bool2Vis}}" />
|
||||
</StatusBarItem>
|
||||
</StatusBar>
|
||||
</Grid>
|
||||
|
||||
Reference in New Issue
Block a user