From a98affad824d9df04d32220c58657d66b53702d5 Mon Sep 17 00:00:00 2001 From: git_rabbit Date: Fri, 23 Jan 2026 09:38:16 +0800 Subject: [PATCH 1/9] =?UTF-8?q?chore:=20=E6=B7=BB=E5=8A=A0=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E5=92=8CVS=20Code?= =?UTF-8?q?=E8=B0=83=E8=AF=95=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加global.json设置.NET SDK版本 添加VS Code的launch.json和tasks.json调试配置 --- .vscode/launch.json | 35 +++++++++++++++++++++++++++++++++++ .vscode/tasks.json | 41 +++++++++++++++++++++++++++++++++++++++++ global.json | 6 ++++++ 3 files changed, 82 insertions(+) create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json create mode 100644 global.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..84d662e1 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,35 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // 使用 IntelliSense 找出 C# 调试存在哪些属性 + // 将悬停用于现有属性的说明 + // 有关详细信息,请访问 https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md。 + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // 如果已更改目标框架,请确保更新程序路径。 + "program": "${workspaceFolder}/ZR.Admin.WebApi/bin/Debug/net7.0/ZR.Admin.WebApi.dll", + "args": [], + "cwd": "${workspaceFolder}/ZR.Admin.WebApi", + "stopAtEntry": false, + // 启用在启动 ASP.NET Core 时启动 Web 浏览器。有关详细信息: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser + "serverReadyAction": { + "action": "openExternally", + "pattern": "\\bNow listening on:\\s+(https?://\\S+)" + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..cf10ff1e --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/global.json b/global.json new file mode 100644 index 00000000..95abff66 --- /dev/null +++ b/global.json @@ -0,0 +1,6 @@ +{ + "sdk": { + "version": "7.0.410", + "rollForward": "latestFeature" + } +} \ No newline at end of file From 28cd87467dec0d92ccbd1922ba84ecf994249fe2 Mon Sep 17 00:00:00 2001 From: git_rabbit Date: Fri, 23 Jan 2026 10:06:18 +0800 Subject: [PATCH 2/9] =?UTF-8?q?=E9=9A=90=E8=97=8F=E4=B8=8D=E5=BF=85?= =?UTF-8?q?=E8=A6=81=E6=96=87=E4=BB=B6=EF=BC=8C=E6=B7=BB=E5=8A=A0GP12?= =?UTF-8?q?=E8=A7=A6=E6=91=B8=E5=B1=8F=E6=89=93=E5=8D=B0=E6=8A=9B=E5=85=89?= =?UTF-8?q?=EF=BC=8C=E6=89=93=E7=A3=A8=E6=A0=87=E7=AD=BE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + ZR.Service/mes/qc/gp12/QcGp12Service.cs | 83 +++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 11b55864..c1690b57 100644 --- a/.gitignore +++ b/.gitignore @@ -264,3 +264,4 @@ __pycache__/ /ZR.Admin.WebApi/wwwroot/2025/1213 /.gitignore /ZR.Admin.WebApi/wwwroot/Generatecode +/.trae diff --git a/ZR.Service/mes/qc/gp12/QcGp12Service.cs b/ZR.Service/mes/qc/gp12/QcGp12Service.cs index bb374ae2..1fa5e830 100644 --- a/ZR.Service/mes/qc/gp12/QcGp12Service.cs +++ b/ZR.Service/mes/qc/gp12/QcGp12Service.cs @@ -6,10 +6,12 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using ZR.Model.Business; using ZR.Model.Dto; +using ZR.Model.MES.qc.DTO; using ZR.Model.MES.wms; using ZR.Model.MES.wms.Dto; using ZR.Service.Business.IBusinessService; using ZR.Service.Utils; +using ZR.Service.mqtt; namespace ZR.Service.Business { @@ -19,6 +21,13 @@ namespace ZR.Service.Business [AppService(ServiceType = typeof(IQcGp12Service), ServiceLifetime = LifeTime.Transient)] public class QcGp12Service : BaseService, IQcGp12Service { + private readonly MqttService _mqttService; + + public QcGp12Service(MqttService mqttService) + { + _mqttService = mqttService; + } + public QcGp12LabelAnalysisDto AnalyzeLabelToDto(string label, int type) { QcGp12LabelAnalysisDto labelAnalysisDto = @@ -736,22 +745,35 @@ namespace ZR.Service.Business Context.Insertable(qcGp12Log).ExecuteCommand(); // 提交事务 Context.Ado.CommitTran(); + + // 发送mqtt消息通知打印抛光/打磨标签 + // 发送抛光标签打印消息 + if (qcGp12Workorder.PolishNumber > 0) + { + SendLabelPrintMqttMessage(qcGp12Workorder, 1, qcGp12Workorder.PolishNumber.Value); + } + // 发送打磨标签打印消息 + if (qcGp12Workorder.DamoNumber > 0) + { + SendLabelPrintMqttMessage(qcGp12Workorder, 2, qcGp12Workorder.DamoNumber.Value); + } + // 插入成品入库单 _ = Task.Run(() => { ProFinishedProductReceiptService proFinishedProductReceiptService = new ProFinishedProductReceiptService(); - + // 生成ReceiptNo:GP+日期YYYYMMDD+0001顺序递增 string today = nowTime.ToString("yyyyMMdd"); string receiptNoPrefix = $"GP{today}"; - + // 查询今天已存在的最大单号 var lastReceipt = Context .Queryable() .Where(it => it.ReceiptNo.StartsWith(receiptNoPrefix)) .OrderBy(it => it.ReceiptNo, OrderByType.Desc) .First(); - + string newReceiptNo; if (lastReceipt != null && !string.IsNullOrEmpty(lastReceipt.ReceiptNo)) { @@ -771,7 +793,7 @@ namespace ZR.Service.Business newReceiptNo = $"{receiptNoPrefix}0001"; } // 箱数 - int _packageCount = Context.Queryable().Where(it=>it.WorkOrder == qcGp12Workorder.WorkOrder).Where(it => it.LabelType == 1).Count(); + int _packageCount = Context.Queryable().Where(it => it.WorkOrder == qcGp12Workorder.WorkOrder).Where(it => it.LabelType == 1).Count(); // 工单号 MaterialUtils materialUtils = new MaterialUtils(); ResultionPackageCodeDto packageCodeDto = materialUtils.ResolutionPackage(qcGp12Workorder.Label); @@ -781,7 +803,8 @@ namespace ZR.Service.Business _workOrder = packageCodeDto.WorkoderID; } - ProFinishedProductReceipt newModel = new() { + ProFinishedProductReceipt newModel = new() + { ReceiptNo = newReceiptNo, SiteNo = qcGp12Workorder.SiteNo, WorkOrder = _workOrder, @@ -1002,5 +1025,55 @@ namespace ZR.Service.Business return Guid.NewGuid().ToString("N").Substring(0, 10); // Generate a 10-character unique ID } + /// + /// 发送标签打印MQTT消息 + /// + /// 工单信息 + /// 标签类型:1-抛光,2-打磨 + /// 数量 + private void SendLabelPrintMqttMessage(QcGp12ServiceWorkorder workorder, int labelType, int quantity) + { + try + { + if (quantity <= 0) + { + return; + } + + string labelCode = labelType == 1 ? "Type=DeNoPG" : "Type=DeNoDM"; + string path = labelType == 1 ? "D:\\RIZO\\label\\抛光送货单.btw" : "D:\\RIZO\\label\\打磨送货单.btw"; + string name = labelType == 1 ? "包装抛光送货单标签打印" : "包装打磨送货单标签打印"; + + var printDto = new PrintDeliveryNoteDto + { + Path = path, + SiteNo = workorder.SiteNo, + Name = name, + PartNumber = workorder.PartNumber, + Description = workorder.Description, + Color = workorder.Color, + Specification = workorder.Specification, + WorkOrder = workorder.WorkOrder, + PackageCode = workorder.WorkOrder, + Team = workorder.Team, + Sort = 1, + ProductionTime = workorder.WorkOrder, + BatchCode = workorder.WorkOrder, + PackageNum = quantity, + LabelCode = $"{labelCode}^ItemNumber={workorder.PartNumber}^Order={workorder.WorkOrder}^Qty={quantity}", + LabelType = 1, + CreatedTime = DateTime.Now.ToString() + }; + + string message = JsonSerializer.Serialize(printDto); + _mqttService.PublishAsync("Print/Label", message, MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce); + } + catch (Exception ex) + { + // 记录异常但不影响主流程 + Console.WriteLine($"发送标签打印MQTT消息失败: {ex.Message}"); + } + } + } } From d4613ab8931c0260d8b8033febbbf81489fd3cfa Mon Sep 17 00:00:00 2001 From: git_rabbit Date: Fri, 23 Jan 2026 11:48:19 +0800 Subject: [PATCH 3/9] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=E6=A0=87?= =?UTF-8?q?=E7=AD=BE=E6=89=93=E5=8D=B0=E5=8A=9F=E8=83=BD=E5=B9=B6=E8=B0=83?= =?UTF-8?q?=E6=95=B4MQTT=E4=B8=BB=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将ProFinishedProductReceiptService中的_receiptLogService改为局部变量 - 统一GP12和后道标签打印的MQTT主题格式 - 调整标签打印名称以更准确反映业务场景 - 在后道服务中新增标签打印MQTT消息发送功能 --- .../pro/ProFinishedProductReceiptService.cs | 3 +- ZR.Service/mes/qc/backend/QcBackEndService.cs | 70 ++++++++++++++++++- ZR.Service/mes/qc/gp12/QcGp12Service.cs | 6 +- 3 files changed, 73 insertions(+), 6 deletions(-) diff --git a/ZR.Service/mes/pro/ProFinishedProductReceiptService.cs b/ZR.Service/mes/pro/ProFinishedProductReceiptService.cs index 30c0147f..d716ba89 100644 --- a/ZR.Service/mes/pro/ProFinishedProductReceiptService.cs +++ b/ZR.Service/mes/pro/ProFinishedProductReceiptService.cs @@ -18,7 +18,6 @@ namespace ZR.Service.Business [AppService(ServiceType = typeof(IProFinishedProductReceiptService), ServiceLifetime = LifeTime.Transient)] public class ProFinishedProductReceiptService : BaseService, IProFinishedProductReceiptService { - private readonly IProFinishedProductReceiptLogService _receiptLogService; /// /// 查询MES成品入库单主表(含产品信息及标签打印状态)列表 @@ -61,7 +60,7 @@ namespace ZR.Service.Business /// public ProFinishedProductReceipt AddProFinishedProductReceipt(ProFinishedProductReceipt model) { - + ProFinishedProductReceiptLogService _receiptLogService = new (); try { diff --git a/ZR.Service/mes/qc/backend/QcBackEndService.cs b/ZR.Service/mes/qc/backend/QcBackEndService.cs index c8c8eccd..24883b57 100644 --- a/ZR.Service/mes/qc/backend/QcBackEndService.cs +++ b/ZR.Service/mes/qc/backend/QcBackEndService.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using ZR.Common.MqttHelper; using ZR.Model.Business; using ZR.Model.Dto; +using ZR.Model.MES.qc.DTO; using ZR.Model.MES.wms; using ZR.Model.MES.wms.Dto; using ZR.Service.Business.IBusinessService; @@ -25,11 +26,13 @@ namespace ZR.Service.Business { private readonly MqttService _mqttService; // 注入MqttService private readonly ILogger _logger; + private readonly IProFinishedProductReceiptService _proFinishedProductReceiptService; - public QcBackEndService(MqttService mqttService, ILogger logger) + public QcBackEndService(MqttService mqttService, ILogger logger, IProFinishedProductReceiptService proFinishedProductReceiptService) { _mqttService = mqttService; _logger = logger; + _proFinishedProductReceiptService = proFinishedProductReceiptService; } public QcBackEndLabelAnalysisDto AnalyzeLabelToDto(string label, int type) @@ -1237,6 +1240,19 @@ namespace ZR.Service.Business Context.Insertable(qcBackEndLog).ExecuteCommand(); // 提交事务 Context.Ado.CommitTran(); + + // 发送mqtt消息通知打印抛光/打磨标签 + // 发送抛光标签打印消息 + if (qcBackEndWorkorder.PolishNumber > 0) + { + SendLabelPrintMqttMessage(qcBackEndWorkorder, 1, qcBackEndWorkorder.PolishNumber.Value); + } + // 发送打磨标签打印消息 + if (qcBackEndWorkorder.DamoNumber > 0) + { + SendLabelPrintMqttMessage(qcBackEndWorkorder, 2, qcBackEndWorkorder.DamoNumber.Value); + } + // 插入成品入库单 _ = Task.Run(() => { @@ -1519,6 +1535,58 @@ namespace ZR.Service.Business return Guid.NewGuid().ToString("N").Substring(0, 10); // Generate a 10-character unique ID } + /// + /// 发送标签打印MQTT消息 + /// + /// 工单信息 + /// 标签类型:1-抛光,2-打磨 + /// 数量 + private void SendLabelPrintMqttMessage(QcBackEndServiceWorkorder workorder, int labelType, int quantity) + { + try + { + if (quantity <= 0) + { + return; + } + + string mqttTopic = "shgg_mes/backEnd/label_print/print/PGDM"; + string labelCode = labelType == 1 ? "Type=DeNoPG" : "Type=DeNoDM"; + string path = labelType == 1 ? "D:\\RIZO\\label\\抛光送货单.btw" : "D:\\RIZO\\label\\打磨送货单.btw"; + string name = labelType == 1 ? "后道抛光送货单标签打印" : "后道打磨送货单标签打印"; + + var printDto = new PrintDeliveryNoteDto + { + Path = path, + SiteNo = workorder.SiteNo, + Name = name, + PartNumber = workorder.PartNumber, + Description = workorder.Description, + Color = workorder.Color, + Specification = workorder.Specification, + WorkOrder = workorder.WorkOrder, + PackageCode = workorder.WorkOrder, + Team = workorder.Team, + Sort = 1, + ProductionTime = workorder.WorkOrder, + BatchCode = workorder.WorkOrder, + PackageNum = quantity, + LabelCode = $"{labelCode}^ItemNumber={workorder.PartNumber}^Order={workorder.WorkOrder}^Qty={quantity}", + LabelType = 1, + CreatedTime = DateTime.Now.ToString() + }; + + string message = JsonSerializer.Serialize(printDto); + _mqttService.PublishAsync(mqttTopic, message, MqttQualityOfServiceLevel.AtLeastOnce); + _logger.LogInformation($"发送后道标签打印MQTT消息成功: {mqttTopic}"); + } + catch (Exception ex) + { + // 记录异常但不影响主流程 + _logger.LogError(ex, "发送后道标签打印MQTT消息失败"); + } + } + /// /// 打印特殊包装标签 /// diff --git a/ZR.Service/mes/qc/gp12/QcGp12Service.cs b/ZR.Service/mes/qc/gp12/QcGp12Service.cs index 1fa5e830..b743e33b 100644 --- a/ZR.Service/mes/qc/gp12/QcGp12Service.cs +++ b/ZR.Service/mes/qc/gp12/QcGp12Service.cs @@ -1039,10 +1039,10 @@ namespace ZR.Service.Business { return; } - + string mqttTopic = $"shgg_mes/gp12/label_print/print/PGDM"; string labelCode = labelType == 1 ? "Type=DeNoPG" : "Type=DeNoDM"; string path = labelType == 1 ? "D:\\RIZO\\label\\抛光送货单.btw" : "D:\\RIZO\\label\\打磨送货单.btw"; - string name = labelType == 1 ? "包装抛光送货单标签打印" : "包装打磨送货单标签打印"; + string name = labelType == 1 ? "GP12抛光送货单标签打印" : "GP12打磨送货单标签打印"; var printDto = new PrintDeliveryNoteDto { @@ -1066,7 +1066,7 @@ namespace ZR.Service.Business }; string message = JsonSerializer.Serialize(printDto); - _mqttService.PublishAsync("Print/Label", message, MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce); + _mqttService.PublishAsync(mqttTopic, message, MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce); } catch (Exception ex) { From e60a4eee99c445eef21eb015219fac75435f72b3 Mon Sep 17 00:00:00 2001 From: git_rabbit Date: Fri, 23 Jan 2026 14:45:30 +0800 Subject: [PATCH 4/9] =?UTF-8?q?feat(=E6=A0=87=E7=AD=BE=E6=89=93=E5=8D=B0):?= =?UTF-8?q?=20=E6=B7=BB=E5=8A=A0=E6=89=98=E7=9B=98=E5=AE=B9=E9=87=8F?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E5=B9=B6=E6=94=AF=E6=8C=81=E5=88=86=E6=89=B9?= =?UTF-8?q?=E6=89=93=E5=8D=B0=E6=A0=87=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在GP12和后道服务的标签打印功能中,新增托盘容量配置检查。当打印数量超过托盘容量时,自动分批打印标签: 1. 在WmMaterialPackage中添加GP12和后道抛光托盘容量字段 2. 重构标签打印逻辑,支持满箱和零头箱分批打印 3. 添加批量打印方法,优化标签信息生成 --- ZR.Model/MES/wms/Dto/WmMaterialPackageDto.cs | 6 +- ZR.Model/MES/wms/WmMaterialPackage.cs | 12 ++ ZR.Service/mes/qc/backend/QcBackEndService.cs | 174 +++++++++++++++--- ZR.Service/mes/qc/gp12/QcGp12Service.cs | 171 ++++++++++++++--- 4 files changed, 319 insertions(+), 44 deletions(-) diff --git a/ZR.Model/MES/wms/Dto/WmMaterialPackageDto.cs b/ZR.Model/MES/wms/Dto/WmMaterialPackageDto.cs index fc342f41..4f60ee8e 100644 --- a/ZR.Model/MES/wms/Dto/WmMaterialPackageDto.cs +++ b/ZR.Model/MES/wms/Dto/WmMaterialPackageDto.cs @@ -5,7 +5,7 @@ namespace ZR.Model.MES.wms.Dto /// /// 查询对象 /// - public class WmMaterialPackageQueryDto : PagerInfo + public class WmMaterialPackageQueryDto : PagerInfo { } @@ -33,6 +33,10 @@ namespace ZR.Model.MES.wms.Dto public int? PackageProductionPolishPalletNum { get; set; } + public int? PackageGP12PolishPalletNum { get; set; } + + public int? PackageBackendPolishPalletNum { get; set; } + public DateTime? CreateTime { get; set; } public string CreateBy { get; set; } diff --git a/ZR.Model/MES/wms/WmMaterialPackage.cs b/ZR.Model/MES/wms/WmMaterialPackage.cs index 0b938a61..6dba9b4b 100644 --- a/ZR.Model/MES/wms/WmMaterialPackage.cs +++ b/ZR.Model/MES/wms/WmMaterialPackage.cs @@ -58,6 +58,18 @@ namespace ZR.Model.MES.wms [SugarColumn(ColumnName = "package_production_polish_pallet_num")] public int? PackageProductionPolishPalletNum { get; set; } + /// + /// 产线包装抛光品托盘产品数 + /// + [SugarColumn(ColumnName = "pacakge_gp12_polish_pallet_num")] + public int? PackageGP12PolishPalletNum { get; set; } + + /// + /// 产线包装抛光品托盘产品数 + /// + [SugarColumn(ColumnName = "package_backend_polish_pallet_num")] + public int? PackageBackendPolishPalletNum { get; set; } + /// /// 创建时间 /// diff --git a/ZR.Service/mes/qc/backend/QcBackEndService.cs b/ZR.Service/mes/qc/backend/QcBackEndService.cs index 24883b57..51407ec8 100644 --- a/ZR.Service/mes/qc/backend/QcBackEndService.cs +++ b/ZR.Service/mes/qc/backend/QcBackEndService.cs @@ -1535,6 +1535,12 @@ namespace ZR.Service.Business return Guid.NewGuid().ToString("N").Substring(0, 10); // Generate a 10-character unique ID } + /// + /// 发送标签打印MQTT消息 + /// + /// 工单信息 + /// 标签类型:1-抛光,2-打磨 + /// 数量 /// /// 发送标签打印MQTT消息 /// @@ -1550,35 +1556,36 @@ namespace ZR.Service.Business return; } + // 1. 基本配置 string mqttTopic = "shgg_mes/backEnd/label_print/print/PGDM"; string labelCode = labelType == 1 ? "Type=DeNoPG" : "Type=DeNoDM"; string path = labelType == 1 ? "D:\\RIZO\\label\\抛光送货单.btw" : "D:\\RIZO\\label\\打磨送货单.btw"; string name = labelType == 1 ? "后道抛光送货单标签打印" : "后道打磨送货单标签打印"; - var printDto = new PrintDeliveryNoteDto + // 2. 抛光标签特殊处理:检查托盘配置 + if (labelType == 1) { - Path = path, - SiteNo = workorder.SiteNo, - Name = name, - PartNumber = workorder.PartNumber, - Description = workorder.Description, - Color = workorder.Color, - Specification = workorder.Specification, - WorkOrder = workorder.WorkOrder, - PackageCode = workorder.WorkOrder, - Team = workorder.Team, - Sort = 1, - ProductionTime = workorder.WorkOrder, - BatchCode = workorder.WorkOrder, - PackageNum = quantity, - LabelCode = $"{labelCode}^ItemNumber={workorder.PartNumber}^Order={workorder.WorkOrder}^Qty={quantity}", - LabelType = 1, - CreatedTime = DateTime.Now.ToString() - }; + // 查询零件的托盘配置 + WmMaterialPackage packageConfig = Context.Queryable() + .Where(it => it.RecordType == "零件") + .Where(it => it.PartNumber == workorder.PartNumber) + .First(); - string message = JsonSerializer.Serialize(printDto); - _mqttService.PublishAsync(mqttTopic, message, MqttQualityOfServiceLevel.AtLeastOnce); - _logger.LogInformation($"发送后道标签打印MQTT消息成功: {mqttTopic}"); + // 检查是否有后道抛光托盘配置 + if (packageConfig != null && packageConfig.PackageBackendPolishPalletNum != null) + { + int polishPalletCapacity = packageConfig.PackageBackendPolishPalletNum.Value; + if (quantity > polishPalletCapacity) + { + // 分批次打印多个标签 + SendBatchPrintLabels(workorder, mqttTopic, labelCode, path, name, quantity, polishPalletCapacity); + return; + } + } + } + + // 3. 默认打印单个标签 + SendSinglePrintLabel(workorder, mqttTopic, labelCode, path, name, quantity, 1); } catch (Exception ex) { @@ -1587,6 +1594,129 @@ namespace ZR.Service.Business } } + /// + /// 分批次打印标签 + /// + /// 工单信息 + /// MQTT主题 + /// 标签代码 + /// 标签模板路径 + /// 标签名称 + /// 总数量 + /// 托盘容量 + private void SendBatchPrintLabels(QcBackEndServiceWorkorder workorder, string mqttTopic, string labelCode, string path, string name, int totalQuantity, int palletCapacity) + { + int fullPalletCount = totalQuantity / palletCapacity; + int remainderCount = totalQuantity % palletCapacity; + + // 打印满托盘标签 + for (int i = 1; i <= fullPalletCount; i++) + { + SendFullPalletPrintLabel(workorder, mqttTopic, labelCode, path, name, palletCapacity, i); + } + + // 打印剩余标签 + if (remainderCount > 0) + { + SendRemainderPrintLabel(workorder, mqttTopic, labelCode, path, name, remainderCount, fullPalletCount); + } + } + + /// + /// 打印单个标签 + /// + /// 工单信息 + /// MQTT主题 + /// 标签代码 + /// 标签模板路径 + /// 标签名称 + /// 数量 + /// 批次索引 + private void SendSinglePrintLabel(QcBackEndServiceWorkorder workorder, string mqttTopic, string labelCode, string path, string name, int quantity, int batchIndex) + { + var printDto = CreatePrintDeliveryNoteDto(workorder, path, name, quantity, workorder.WorkOrder, batchIndex, labelCode); + string message = JsonSerializer.Serialize(printDto); + _mqttService.PublishAsync(mqttTopic, message, MqttQualityOfServiceLevel.AtLeastOnce); + _logger.LogInformation($"发送后道标签打印MQTT消息成功: {mqttTopic}"); + } + + /// + /// 打印满托盘标签 + /// + /// 工单信息 + /// MQTT主题 + /// 标签代码 + /// 标签模板路径 + /// 标签名称 + /// 数量 + /// 批次索引 + private void SendFullPalletPrintLabel(QcBackEndServiceWorkorder workorder, string mqttTopic, string labelCode, string path, string name, int quantity, int batchIndex) + { + var printDto = CreatePrintDeliveryNoteDto(workorder, path, $"{name}(满箱)第{batchIndex}箱", quantity, $"{workorder.WorkOrder}_{batchIndex}", batchIndex, labelCode, batchIndex); + string message = JsonSerializer.Serialize(printDto); + _mqttService.PublishAsync(mqttTopic, message, MqttQualityOfServiceLevel.AtLeastOnce); + _logger.LogInformation($"发送后道抛光满箱标签打印MQTT消息成功: {mqttTopic}, 第{batchIndex}箱"); + } + + /// + /// 打印剩余标签 + /// + /// 工单信息 + /// MQTT主题 + /// 标签代码 + /// 标签模板路径 + /// 标签名称 + /// 数量 + /// 满托盘数量 + private void SendRemainderPrintLabel(QcBackEndServiceWorkorder workorder, string mqttTopic, string labelCode, string path, string name, int quantity, int fullPalletCount) + { + int batchIndex = fullPalletCount + 1; + var printDto = CreatePrintDeliveryNoteDto(workorder, path, $"{name}(零头箱)", quantity, $"{workorder.WorkOrder}_零头", batchIndex, labelCode, batchIndex); + string message = JsonSerializer.Serialize(printDto); + _mqttService.PublishAsync(mqttTopic, message, MqttQualityOfServiceLevel.AtLeastOnce); + _logger.LogInformation($"发送后道抛光零头箱标签打印MQTT消息成功: {mqttTopic}"); + } + + /// + /// 创建打印送货单DTO + /// + /// 工单信息 + /// 标签模板路径 + /// 标签名称 + /// 数量 + /// 包装代码 + /// 排序 + /// 标签代码 + /// 批次索引(可选,用于生成标签代码) + /// 打印送货单DTO + private PrintDeliveryNoteDto CreatePrintDeliveryNoteDto(QcBackEndServiceWorkorder workorder, string path, string name, int quantity, string packageCode, int sort, string labelCode, int? batchIndex = null) + { + string finalLabelCode = batchIndex.HasValue + ? $"{labelCode}^ItemNumber={workorder.PartNumber}^Order={workorder.WorkOrder}^Qty={quantity}^Batch={batchIndex}" + : $"{labelCode}^ItemNumber={workorder.PartNumber}^Order={workorder.WorkOrder}^Qty={quantity}"; + + return new PrintDeliveryNoteDto + { + Path = path, + SiteNo = workorder.SiteNo, + Name = name, + PartNumber = workorder.PartNumber, + Description = workorder.Description, + Color = workorder.Color, + Specification = workorder.Specification, + WorkOrder = workorder.WorkOrder, + PackageCode = packageCode, + Team = workorder.Team, + Sort = sort, + ProductionTime = workorder.WorkOrder, + BatchCode = workorder.WorkOrder, + PackageNum = quantity, + LabelCode = finalLabelCode, + LabelType = 1, + CreatedTime = DateTime.Now.ToString() + }; + } + /// /// 打印特殊包装标签 /// diff --git a/ZR.Service/mes/qc/gp12/QcGp12Service.cs b/ZR.Service/mes/qc/gp12/QcGp12Service.cs index b743e33b..f0eb8a46 100644 --- a/ZR.Service/mes/qc/gp12/QcGp12Service.cs +++ b/ZR.Service/mes/qc/gp12/QcGp12Service.cs @@ -1025,6 +1025,12 @@ namespace ZR.Service.Business return Guid.NewGuid().ToString("N").Substring(0, 10); // Generate a 10-character unique ID } + /// + /// 发送标签打印MQTT消息 + /// + /// 工单信息 + /// 标签类型:1-抛光,2-打磨 + /// 数量 /// /// 发送标签打印MQTT消息 /// @@ -1039,34 +1045,37 @@ namespace ZR.Service.Business { return; } + + // 1. 基本配置 string mqttTopic = $"shgg_mes/gp12/label_print/print/PGDM"; string labelCode = labelType == 1 ? "Type=DeNoPG" : "Type=DeNoDM"; string path = labelType == 1 ? "D:\\RIZO\\label\\抛光送货单.btw" : "D:\\RIZO\\label\\打磨送货单.btw"; string name = labelType == 1 ? "GP12抛光送货单标签打印" : "GP12打磨送货单标签打印"; - var printDto = new PrintDeliveryNoteDto + // 2. 抛光标签特殊处理:检查托盘配置 + if (labelType == 1) { - Path = path, - SiteNo = workorder.SiteNo, - Name = name, - PartNumber = workorder.PartNumber, - Description = workorder.Description, - Color = workorder.Color, - Specification = workorder.Specification, - WorkOrder = workorder.WorkOrder, - PackageCode = workorder.WorkOrder, - Team = workorder.Team, - Sort = 1, - ProductionTime = workorder.WorkOrder, - BatchCode = workorder.WorkOrder, - PackageNum = quantity, - LabelCode = $"{labelCode}^ItemNumber={workorder.PartNumber}^Order={workorder.WorkOrder}^Qty={quantity}", - LabelType = 1, - CreatedTime = DateTime.Now.ToString() - }; + // 查询零件的托盘配置 + WmMaterialPackage packageConfig = Context.Queryable() + .Where(it => it.RecordType == "零件") + .Where(it => it.PartNumber == workorder.PartNumber) + .First(); - string message = JsonSerializer.Serialize(printDto); - _mqttService.PublishAsync(mqttTopic, message, MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce); + // 检查是否有GP12抛光托盘配置 + if (packageConfig != null && packageConfig.PackageGP12PolishPalletNum != null) + { + int polishPalletCapacity = packageConfig.PackageGP12PolishPalletNum.Value; + if (quantity > polishPalletCapacity) + { + // 分批次打印多个标签 + SendBatchPrintLabels(workorder, mqttTopic, labelCode, path, name, quantity, polishPalletCapacity); + return; + } + } + } + + // 3. 默认打印单个标签 + SendSinglePrintLabel(workorder, mqttTopic, labelCode, path, name, quantity, 1); } catch (Exception ex) { @@ -1075,5 +1084,125 @@ namespace ZR.Service.Business } } + /// + /// 分批次打印标签 + /// + /// 工单信息 + /// MQTT主题 + /// 标签代码 + /// 标签模板路径 + /// 标签名称 + /// 总数量 + /// 托盘容量 + private void SendBatchPrintLabels(QcGp12ServiceWorkorder workorder, string mqttTopic, string labelCode, string path, string name, int totalQuantity, int palletCapacity) + { + int fullPalletCount = totalQuantity / palletCapacity; + int remainderCount = totalQuantity % palletCapacity; + + // 打印满托盘标签 + for (int i = 1; i <= fullPalletCount; i++) + { + SendFullPalletPrintLabel(workorder, mqttTopic, labelCode, path, name, palletCapacity, i); + } + + // 打印剩余标签 + if (remainderCount > 0) + { + SendRemainderPrintLabel(workorder, mqttTopic, labelCode, path, name, remainderCount, fullPalletCount); + } + } + + /// + /// 打印单个标签 + /// + /// 工单信息 + /// MQTT主题 + /// 标签代码 + /// 标签模板路径 + /// 标签名称 + /// 数量 + /// 批次索引 + private void SendSinglePrintLabel(QcGp12ServiceWorkorder workorder, string mqttTopic, string labelCode, string path, string name, int quantity, int batchIndex) + { + var printDto = CreatePrintDeliveryNoteDto(workorder, path, name, quantity, workorder.WorkOrder, batchIndex, labelCode); + string message = JsonSerializer.Serialize(printDto); + _mqttService.PublishAsync(mqttTopic, message, MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce); + } + + /// + /// 打印满托盘标签 + /// + /// 工单信息 + /// MQTT主题 + /// 标签代码 + /// 标签模板路径 + /// 标签名称 + /// 数量 + /// 批次索引 + private void SendFullPalletPrintLabel(QcGp12ServiceWorkorder workorder, string mqttTopic, string labelCode, string path, string name, int quantity, int batchIndex) + { + var printDto = CreatePrintDeliveryNoteDto(workorder, path, $"{name}(满箱)第{batchIndex}箱", quantity, $"{workorder.WorkOrder}_{batchIndex}", batchIndex, labelCode, batchIndex); + string message = JsonSerializer.Serialize(printDto); + _mqttService.PublishAsync(mqttTopic, message, MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce); + } + + /// + /// 打印剩余标签 + /// + /// 工单信息 + /// MQTT主题 + /// 标签代码 + /// 标签模板路径 + /// 标签名称 + /// 数量 + /// 满托盘数量 + private void SendRemainderPrintLabel(QcGp12ServiceWorkorder workorder, string mqttTopic, string labelCode, string path, string name, int quantity, int fullPalletCount) + { + int batchIndex = fullPalletCount + 1; + var printDto = CreatePrintDeliveryNoteDto(workorder, path, $"{name}(零头箱)", quantity, $"{workorder.WorkOrder}_零头", batchIndex, labelCode, batchIndex); + string message = JsonSerializer.Serialize(printDto); + _mqttService.PublishAsync(mqttTopic, message, MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce); + } + + /// + /// 创建打印送货单DTO + /// + /// 工单信息 + /// 标签模板路径 + /// 标签名称 + /// 数量 + /// 包装代码 + /// 排序 + /// 标签代码 + /// 批次索引(可选,用于生成标签代码) + /// 打印送货单DTO + private PrintDeliveryNoteDto CreatePrintDeliveryNoteDto(QcGp12ServiceWorkorder workorder, string path, string name, int quantity, string packageCode, int sort, string labelCode, int? batchIndex = null) + { + string finalLabelCode = batchIndex.HasValue + ? $"{labelCode}^ItemNumber={workorder.PartNumber}^Order={workorder.WorkOrder}^Qty={quantity}^Batch={batchIndex}" + : $"{labelCode}^ItemNumber={workorder.PartNumber}^Order={workorder.WorkOrder}^Qty={quantity}"; + + return new PrintDeliveryNoteDto + { + Path = path, + SiteNo = workorder.SiteNo, + Name = name, + PartNumber = workorder.PartNumber, + Description = workorder.Description, + Color = workorder.Color, + Specification = workorder.Specification, + WorkOrder = workorder.WorkOrder, + PackageCode = packageCode, + Team = workorder.Team, + Sort = sort, + ProductionTime = workorder.WorkOrder, + BatchCode = workorder.WorkOrder, + PackageNum = quantity, + LabelCode = finalLabelCode, + LabelType = 1, + CreatedTime = DateTime.Now.ToString() + }; + } + } } From 525b7ea509fed1dbc9f2393d4d874b11ed909bc1 Mon Sep 17 00:00:00 2001 From: git_rabbit Date: Mon, 26 Jan 2026 10:55:27 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E6=89=93=E5=8D=B0=E5=9C=B0=E5=9D=80?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ZR.Service/mes/qc/backend/QcBackEndService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZR.Service/mes/qc/backend/QcBackEndService.cs b/ZR.Service/mes/qc/backend/QcBackEndService.cs index 51407ec8..1627f1b4 100644 --- a/ZR.Service/mes/qc/backend/QcBackEndService.cs +++ b/ZR.Service/mes/qc/backend/QcBackEndService.cs @@ -1559,7 +1559,7 @@ namespace ZR.Service.Business // 1. 基本配置 string mqttTopic = "shgg_mes/backEnd/label_print/print/PGDM"; string labelCode = labelType == 1 ? "Type=DeNoPG" : "Type=DeNoDM"; - string path = labelType == 1 ? "D:\\RIZO\\label\\抛光送货单.btw" : "D:\\RIZO\\label\\打磨送货单.btw"; + string path = labelType == 1 ? "C:\\Program Files\\MES\\label\\送货单\\抛光送货单.btw" : "C:\\Program Files\\MES\\label\\送货单\\打磨送货单.btw"; string name = labelType == 1 ? "后道抛光送货单标签打印" : "后道打磨送货单标签打印"; // 2. 抛光标签特殊处理:检查托盘配置 From 37c19fbd24fc0ba6bc90a87e6bf1107bb409e11b Mon Sep 17 00:00:00 2001 From: git_rabbit Date: Mon, 26 Jan 2026 10:57:01 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E5=8D=95=E6=8D=AE=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ZR.Service/mes/qc/gp12/QcGp12Service.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ZR.Service/mes/qc/gp12/QcGp12Service.cs b/ZR.Service/mes/qc/gp12/QcGp12Service.cs index f0eb8a46..2f1d53cc 100644 --- a/ZR.Service/mes/qc/gp12/QcGp12Service.cs +++ b/ZR.Service/mes/qc/gp12/QcGp12Service.cs @@ -1025,12 +1025,6 @@ namespace ZR.Service.Business return Guid.NewGuid().ToString("N").Substring(0, 10); // Generate a 10-character unique ID } - /// - /// 发送标签打印MQTT消息 - /// - /// 工单信息 - /// 标签类型:1-抛光,2-打磨 - /// 数量 /// /// 发送标签打印MQTT消息 /// From b4879f821d921a73f34fe513d582119d0f594dba Mon Sep 17 00:00:00 2001 From: git_rabbit Date: Fri, 6 Feb 2026 14:32:46 +0800 Subject: [PATCH 7/9] =?UTF-8?q?feat(tcp):=20=E6=B7=BB=E5=8A=A0TCP=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=99=A8=E6=9C=8D=E5=8A=A1=E5=AE=9E=E7=8E=B0=E5=A4=9A?= =?UTF-8?q?=E5=AE=A2=E6=88=B7=E7=AB=AF=E5=B9=B6=E5=8F=91=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实现基于BackgroundService的TCP服务器,支持多客户端并发连接和消息广播 包含信号去重功能,防止短时间内重复处理相同信号 添加客户端连接管理和统计报告功能 --- ZR.Admin.WebApi/Program.cs | 3 + ZR.Service/tcp/TcpServerService.cs | 441 +++++++++++++++++++++++++++++ 2 files changed, 444 insertions(+) create mode 100644 ZR.Service/tcp/TcpServerService.cs diff --git a/ZR.Admin.WebApi/Program.cs b/ZR.Admin.WebApi/Program.cs index a9d03142..84d677a0 100644 --- a/ZR.Admin.WebApi/Program.cs +++ b/ZR.Admin.WebApi/Program.cs @@ -42,6 +42,9 @@ builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddHostedService(sp => sp.GetRequiredService()); /// =============================================================================== + +// 注册TCP服务器服务 +builder.Services.AddHostedService(); // 跨域配置 builder.Services.AddCors(builder.Configuration); // 显示logo diff --git a/ZR.Service/tcp/TcpServerService.cs b/ZR.Service/tcp/TcpServerService.cs new file mode 100644 index 00000000..a78caf94 --- /dev/null +++ b/ZR.Service/tcp/TcpServerService.cs @@ -0,0 +1,441 @@ +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Concurrent; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace ZR.Service.tcp +{ + /// + /// 信号去重记录 + /// + public class SignalDeduplicationRecord + { + /// + /// 信号唯一标识 + /// + public string SignalId { get; set; } + + /// + /// 接收时间戳(毫秒) + /// + public long Timestamp { get; set; } + } + + /// + /// TCP服务器服务 + /// 基于BackgroundService实现,支持多客户端并发连接 + /// 监听端口:9090 + /// + public class TcpServerService : BackgroundService + { + private readonly ILogger _logger; + private TcpListener _tcpListener; + private CancellationTokenSource _cts; + private readonly int _port = 9090; + private readonly string _ipAddress = "0.0.0.0"; // 监听所有网络接口 + + // 线程安全的客户端连接列表,用于管理所有已连接的客户端 + private ConcurrentDictionary _connectedClients; + + // 信号去重相关 + private ConcurrentDictionary _recentSignals; // 键:信号唯一标识,值:时间戳 + private long _deduplicationCount; // 去重统计计数 + private object _deduplicationLock = new object(); // 用于统计计数的锁 + private readonly int _timeWindowMs = 1000; // 时间窗口:1000毫秒 + private readonly int _cleanupIntervalMs = 5000; // 清理间隔:5000毫秒 + + /// + /// 构造函数 + /// + /// 日志服务 + public TcpServerService(ILogger logger) + { + _logger = logger; + _connectedClients = new ConcurrentDictionary(); + _recentSignals = new ConcurrentDictionary(); + _deduplicationCount = 0; + } + + /// + /// 执行TCP服务器逻辑 + /// + /// 停止令牌 + /// + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + // 创建与停止令牌关联的取消令牌源 + _cts = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken); + + try + { + // 初始化TCP监听器 + IPAddress localAddr = IPAddress.Parse(_ipAddress); + _tcpListener = new TcpListener(localAddr, _port); + + // 启动监听器 + _tcpListener.Start(); + _logger.LogInformation($"TCP服务器启动成功,监听地址: {_ipAddress}:{_port}"); + Console.WriteLine($"[TCP服务器] 启动成功,监听地址: {_ipAddress}:{_port}"); + + // 启动定期清理任务 + _ = Task.Run(() => CleanupExpiredSignalsAsync(_cts.Token), _cts.Token); + + // 启动统计报告任务 + _ = Task.Run(() => ReportDeduplicationStatsAsync(_cts.Token), _cts.Token); + + // 循环接受客户端连接 + while (!_cts.Token.IsCancellationRequested) + { + try + { + // 检查是否有挂起的连接 + if (_tcpListener.Pending()) + { + // 接受客户端连接 + TcpClient client = await _tcpListener.AcceptTcpClientAsync(); + string clientEndPoint = client.Client.RemoteEndPoint?.ToString() ?? "未知客户端"; + + // 将客户端添加到连接列表 + _connectedClients.TryAdd(clientEndPoint, client); + _logger.LogInformation($"客户端连接成功: {clientEndPoint},当前连接数: {_connectedClients.Count}"); + Console.WriteLine($"[TCP服务器] 客户端连接成功: {clientEndPoint},当前连接数: {_connectedClients.Count}"); + + // 异步处理客户端连接,避免阻塞主线程 + _ = HandleClientAsync(client, clientEndPoint, _cts.Token); + } + else + { + // 避免CPU占用过高,添加适当延迟 + await Task.Delay(100, _cts.Token); + } + } + catch (OperationCanceledException) + { + // 正常停止,无需处理 + break; + } + catch (Exception ex) + { + _logger.LogError(ex, "接受客户端连接时发生错误"); + Console.WriteLine($"[TCP服务器] 接受客户端连接时发生错误: {ex.Message}"); + // 继续运行,不影响服务器整体 + } + } + } + catch (Exception ex) + { + _logger.LogError(ex, "TCP服务器启动失败"); + Console.WriteLine($"[TCP服务器] 启动失败: {ex.Message}"); + } + finally + { + // 清理所有客户端连接 + foreach (var client in _connectedClients.Values) + { + try + { + client.Close(); + } + catch { } + } + _connectedClients.Clear(); + + // 清理信号记录 + _recentSignals.Clear(); + + // 停止监听器 + _tcpListener?.Stop(); + _logger.LogInformation("TCP服务器已停止"); + Console.WriteLine("[TCP服务器] 已停止"); + } + } + + /// + /// 定期清理过期的信号记录 + /// + /// 取消令牌 + /// + private async Task CleanupExpiredSignalsAsync(CancellationToken cancellationToken) + { + while (!cancellationToken.IsCancellationRequested) + { + try + { + long currentTime = GetCurrentTimestampMs(); + int removedCount = 0; + + // 清理过期的信号记录 + foreach (var signalEntry in _recentSignals) + { + if (currentTime - signalEntry.Value > _timeWindowMs) + { + if (_recentSignals.TryRemove(signalEntry.Key, out _)) + { + removedCount++; + } + } + } + + if (removedCount > 0) + { + _logger.LogInformation($"清理了 {removedCount} 条过期信号记录,剩余 {_recentSignals.Count} 条"); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "清理过期信号记录时发生错误"); + } + + // 等待下一次清理 + await Task.Delay(_cleanupIntervalMs, cancellationToken); + } + } + + /// + /// 报告去重统计信息 + /// + /// 取消令牌 + /// + private async Task ReportDeduplicationStatsAsync(CancellationToken cancellationToken) + { + while (!cancellationToken.IsCancellationRequested) + { + try + { + long currentCount = Interlocked.Exchange(ref _deduplicationCount, 0); + if (currentCount > 0) + { + _logger.LogInformation($"过去5秒内去重了 {currentCount} 条信号"); + Console.WriteLine($"[TCP服务器] 过去5秒内去重了 {currentCount} 条信号"); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "报告去重统计信息时发生错误"); + } + + // 每5秒报告一次 + await Task.Delay(5000, cancellationToken); + } + } + + /// + /// 检查信号是否需要去重 + /// + /// 信号数据 + /// 是否需要去重(true:需要去重,false:不需要去重) + private bool ShouldDeduplicate(string signalData) + { + try + { + // 生成信号唯一标识 + string signalId = GenerateSignalId(signalData); + long currentTime = GetCurrentTimestampMs(); + + // 检查是否存在近期相同的信号 + if (_recentSignals.TryGetValue(signalId, out long existingTime)) + { + // 检查是否在时间窗口内 + if (currentTime - existingTime <= _timeWindowMs) + { + // 记录去重计数 + Interlocked.Increment(ref _deduplicationCount); + _logger.LogInformation($"信号去重:{signalId},时间差:{currentTime - existingTime}ms"); + return true; + } + } + + // 更新或添加信号记录 + _recentSignals[signalId] = currentTime; + return false; + } + catch (Exception ex) + { + _logger.LogError(ex, "信号去重检查时发生错误"); + // 发生错误时,允许信号通过,避免影响主流程 + return false; + } + } + + /// + /// 生成信号唯一标识 + /// + /// 信号数据 + /// 信号唯一标识 + private string GenerateSignalId(string signalData) + { + // 对于shgx/production/changePackagePrevention/XXXX格式的信号,使用完整字符串作为唯一标识 + // 对于其他信号,可以根据具体格式生成唯一标识 + return signalData; + } + + /// + /// 获取当前时间戳(毫秒) + /// + /// 时间戳(毫秒) + private long GetCurrentTimestampMs() + { + // 使用DateTime.UtcNow确保时间一致性,减少系统时间跳变的影响 + return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds; + } + + /// + /// 处理客户端连接 + /// + /// TCP客户端 + /// 客户端端点信息 + /// 取消令牌 + /// + private async Task HandleClientAsync(TcpClient client, string clientEndPoint, CancellationToken cancellationToken) + { + using (client) + using (NetworkStream stream = client.GetStream()) + { + try + { + // 设置读取超时 + client.ReceiveTimeout = 30000; // 30秒 + client.SendTimeout = 30000; // 30秒 + + // 缓冲区大小 + byte[] buffer = new byte[4096]; + int bytesRead; + + // 循环读取客户端数据 + while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0) + { + try + { + // 解析接收到的数据 + string receivedData = Encoding.UTF8.GetString(buffer, 0, bytesRead); + _logger.LogInformation($"从客户端 {clientEndPoint} 接收到数据: {receivedData}"); + Console.WriteLine($"[TCP服务器] 从客户端 {clientEndPoint} 接收到数据: {receivedData}"); + + // 检查是否是需要广播的消息格式 + if (receivedData.StartsWith("shgx/cx/gz/")) + { + // 检查是否需要去重 + if (!ShouldDeduplicate(receivedData)) + { + // 向所有已连接的客户端广播消息 + await BroadcastMessageAsync(receivedData, cancellationToken); + } + else + { + // 信号已去重,记录日志 + Console.WriteLine($"[TCP服务器] 信号已去重: {receivedData}"); + } + } + else + { + // 处理数据并生成响应 + string response = ProcessData(receivedData); + byte[] responseBytes = Encoding.UTF8.GetBytes(response); + + // 发送响应 + await stream.WriteAsync(responseBytes, 0, responseBytes.Length, cancellationToken); + _logger.LogInformation($"向客户端 {clientEndPoint} 发送响应: {response}"); + Console.WriteLine($"[TCP服务器] 向客户端 {clientEndPoint} 发送响应: {response}"); + } + } + catch (Exception ex) + { + _logger.LogError(ex, $"处理客户端 {clientEndPoint} 数据时发生错误"); + Console.WriteLine($"[TCP服务器] 处理客户端 {clientEndPoint} 数据时发生错误: {ex.Message}"); + + // 发送错误响应 + string errorResponse = $"Error: {ex.Message}"; + byte[] errorBytes = Encoding.UTF8.GetBytes(errorResponse); + await stream.WriteAsync(errorBytes, 0, errorBytes.Length, cancellationToken); + } + } + + // 客户端断开连接 + _connectedClients.TryRemove(clientEndPoint, out _); + _logger.LogInformation($"客户端 {clientEndPoint} 断开连接,当前连接数: {_connectedClients.Count}"); + Console.WriteLine($"[TCP服务器] 客户端 {clientEndPoint} 断开连接,当前连接数: {_connectedClients.Count}"); + } + catch (OperationCanceledException) + { + // 正常停止,无需处理 + _connectedClients.TryRemove(clientEndPoint, out _); + } + catch (Exception ex) + { + _logger.LogError(ex, $"处理客户端 {clientEndPoint} 连接时发生错误"); + Console.WriteLine($"[TCP服务器] 处理客户端 {clientEndPoint} 连接时发生错误: {ex.Message}"); + _connectedClients.TryRemove(clientEndPoint, out _); + } + } + } + + /// + /// 向所有已连接的客户端广播消息 + /// + /// 要广播的消息 + /// 取消令牌 + /// + private async Task BroadcastMessageAsync(string message, CancellationToken cancellationToken) + { + _logger.LogInformation($"开始广播消息: {message},目标客户端数: {_connectedClients.Count}"); + Console.WriteLine($"[TCP服务器] 开始广播消息: {message},目标客户端数: {_connectedClients.Count}"); + + byte[] messageBytes = Encoding.UTF8.GetBytes(message); + int broadcastCount = 0; + + // 遍历所有客户端并发送消息 + foreach (var clientEntry in _connectedClients) + { + string clientEndPoint = clientEntry.Key; + TcpClient client = clientEntry.Value; + + try + { + if (client.Connected) + { + // 直接获取网络流,不要使用using块,避免重复释放 + NetworkStream stream = client.GetStream(); + await stream.WriteAsync(messageBytes, 0, messageBytes.Length, cancellationToken); + broadcastCount++; + _logger.LogInformation($"向客户端 {clientEndPoint} 广播消息成功"); + Console.WriteLine($"[TCP服务器] 向客户端 {clientEndPoint} 广播消息成功"); + } + else + { + // 移除已断开的客户端 + _connectedClients.TryRemove(clientEndPoint, out _); + _logger.LogInformation($"客户端 {clientEndPoint} 已断开,从连接列表中移除"); + Console.WriteLine($"[TCP服务器] 客户端 {clientEndPoint} 已断开,从连接列表中移除"); + } + } + catch (Exception ex) + { + _logger.LogError(ex, $"向客户端 {clientEndPoint} 广播消息时发生错误"); + Console.WriteLine($"[TCP服务器] 向客户端 {clientEndPoint} 广播消息时发生错误: {ex.Message}"); + // 移除失败的客户端 + _connectedClients.TryRemove(clientEndPoint, out _); + } + } + + _logger.LogInformation($"广播完成,成功发送到 {broadcastCount} 个客户端"); + Console.WriteLine($"[TCP服务器] 广播完成,成功发送到 {broadcastCount} 个客户端"); + } + + /// + /// 处理接收到的数据 + /// + /// 接收到的数据 + /// 响应数据 + private string ProcessData(string data) + { + // 这里可以根据实际业务需求处理数据 + // 示例:简单回显接收到的数据 + return $"Server response: {data}"; + } + } +} From 6253251d2de94b0ee69a75cdf14ea7349ff27abb Mon Sep 17 00:00:00 2001 From: git_rabbit Date: Wed, 11 Feb 2026 15:26:53 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E6=B7=BB=E5=8A=A0TCP=E8=BD=AC=E5=8F=91?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=88=E6=B5=8B=E8=AF=95=E7=89=88=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ZR.Service/mes/qc/FirstFQCService.cs | 132 +++++++++++++++++++++------ 1 file changed, 106 insertions(+), 26 deletions(-) diff --git a/ZR.Service/mes/qc/FirstFQCService.cs b/ZR.Service/mes/qc/FirstFQCService.cs index 5886fc89..91bfbb0e 100644 --- a/ZR.Service/mes/qc/FirstFQCService.cs +++ b/ZR.Service/mes/qc/FirstFQCService.cs @@ -1,6 +1,8 @@ using System; using System.IO; using System.Linq; +using System.Net.Sockets; +using System.Text; using System.Text.Json; using System.Threading.Tasks; using Infrastructure.Attribute; @@ -559,11 +561,11 @@ namespace ZR.Service.mes.qc x.AsInsertable.ExecuteCommandAsync(); //执行插入 x.AsUpdateable.UpdateColumns(it => new - { - it.UpdatedBy, - it.UpdatedTime, - it.Counter - }) + { + it.UpdatedBy, + it.UpdatedTime, + it.Counter + }) .ExecuteCommandAsync(); //执行更新 ////更新初检报废表 @@ -900,14 +902,70 @@ namespace ZR.Service.mes.qc else if (Now_producting_Workorder_thirty == null) { Now_producting_Workorder_thirty = Now_producting_WorkorderList[0]; + // 发送TCP消息 + if (Now_producting_Workorder_thirty != null && !string.IsNullOrEmpty(Now_producting_Workorder_thirty.FinishedPartNumber)) + { + string message = $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; + _ = SendTcpMessageAsync(message); + } return Now_producting_Workorder_thirty; } else { + // 发送TCP消息 + if (!string.IsNullOrEmpty(Now_producting_Workorder_thirty.FinishedPartNumber)) + { + string message = $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; + _ = SendTcpMessageAsync(message); + } return Now_producting_Workorder_thirty; } } + /// + /// 发送TCP消息到TCP服务器 + /// + /// 要发送的消息 + private async Task SendTcpMessageAsync(string message) + { + try + { + // TCP服务器地址和端口 + string serverAddress = "127.0.0.1"; + int serverPort = 9090; + + // 创建TCP客户端 + using (TcpClient client = new TcpClient()) + { + // 连接到服务器 + await client.ConnectAsync(serverAddress, serverPort); + _logger.LogInformation($"成功连接到TCP服务器: {serverAddress}:{serverPort}"); + + // 获取网络流 + using (NetworkStream stream = client.GetStream()) + { + // 将消息转换为字节数组 + byte[] messageBytes = Encoding.UTF8.GetBytes(message); + + // 发送消息 + await stream.WriteAsync(messageBytes, 0, messageBytes.Length); + _logger.LogInformation($"已发送TCP消息: {message}"); + + // 等待服务器响应(可选) + byte[] responseBuffer = new byte[4096]; + int bytesRead = await stream.ReadAsync(responseBuffer, 0, responseBuffer.Length); + string response = Encoding.UTF8.GetString(responseBuffer, 0, bytesRead); + _logger.LogInformation($"收到TCP服务器响应: {response}"); + } + } + } + catch (Exception ex) + { + _logger.LogError(ex, "发送TCP消息时发生错误"); + Console.WriteLine($"[FirstFQCService] 发送TCP消息时发生错误: {ex.Message}"); + } + } + /// /// 获取下一个生产工单 一检 /// @@ -1035,18 +1093,28 @@ namespace ZR.Service.mes.qc { // 逻辑异常 Now_producting_Workorder_thirty = Now_producting_WorkorderList[0]; + // 发送TCP消息 + if (Now_producting_Workorder_thirty != null && !string.IsNullOrEmpty(Now_producting_Workorder_thirty.FinishedPartNumber)) + { + string message = $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; + _ = SendTcpMessageAsync(message); + } return null; } if (index == Now_producting_WorkorderList.Count() - 1) { // 已经是最后一个了没有 - - return null; } else { Now_producting_Workorder_thirty = Now_producting_WorkorderList[index + 1]; + // 发送TCP消息 + if (Now_producting_Workorder_thirty != null && !string.IsNullOrEmpty(Now_producting_Workorder_thirty.FinishedPartNumber)) + { + string message = $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; + _ = SendTcpMessageAsync(message); + } return Now_producting_Workorder_thirty; } } @@ -1207,6 +1275,12 @@ namespace ZR.Service.mes.qc { // 逻辑异常 Now_producting_Workorder_thirty = Now_producting_WorkorderList[0]; + // 发送TCP消息 + if (Now_producting_Workorder_thirty != null && !string.IsNullOrEmpty(Now_producting_Workorder_thirty.FinishedPartNumber)) + { + string message = $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; + _ = SendTcpMessageAsync(message); + } return null; } if (index == 0) @@ -1217,6 +1291,12 @@ namespace ZR.Service.mes.qc else { Now_producting_Workorder_thirty = Now_producting_WorkorderList[index - 1]; + // 发送TCP消息 + if (Now_producting_Workorder_thirty != null && !string.IsNullOrEmpty(Now_producting_Workorder_thirty.FinishedPartNumber)) + { + string message = $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; + _ = SendTcpMessageAsync(message); + } return Now_producting_Workorder_thirty; } } @@ -3923,11 +4003,11 @@ namespace ZR.Service.mes.qc } } else - { - // 没有配置时使用默认的单个标签打印 - PrintDeliveryNoteDto qualifiedSingleLabelDto = CreateQualifiedSingleLabelDto(first, first.QualifiedNumber.Value); - SendMqttLabelMessage(mqttTopic, qualifiedSingleLabelDto); - } + { + // 没有配置时使用默认的单个标签打印 + PrintDeliveryNoteDto qualifiedSingleLabelDto = CreateQualifiedSingleLabelDto(first, first.QualifiedNumber.Value); + SendMqttLabelMessage(mqttTopic, qualifiedSingleLabelDto); + } if (packageConfig != null && packageConfig.PackageProductionPolishPalletNum != null) { @@ -3961,11 +4041,11 @@ namespace ZR.Service.mes.qc } } else - { - // 没有配置时使用默认的单个标签打印 - PrintDeliveryNoteDto polishSingleLabelDto = CreatePolishSingleLabelDto(first, first.PaoguangTotal.Value); - SendMqttLabelMessage(mqttTopic, polishSingleLabelDto); - } + { + // 没有配置时使用默认的单个标签打印 + PrintDeliveryNoteDto polishSingleLabelDto = CreatePolishSingleLabelDto(first, first.PaoguangTotal.Value); + SendMqttLabelMessage(mqttTopic, polishSingleLabelDto); + } // 使用辅助方法创建打磨标签 @@ -3974,7 +4054,7 @@ namespace ZR.Service.mes.qc } catch (Exception) { - + } return 1; @@ -4054,7 +4134,7 @@ namespace ZR.Service.mes.qc } return 0; } - + /// /// 发送MQTT标签打印消息 /// @@ -4070,7 +4150,7 @@ namespace ZR.Service.mes.qc ) .Wait(); } - + /// /// 创建合格品满箱标签DTO /// @@ -4097,7 +4177,7 @@ namespace ZR.Service.mes.qc CreatedTime = DateTime.Now.ToString() }; } - + /// /// 创建合格品零头箱标签DTO /// @@ -4125,7 +4205,7 @@ namespace ZR.Service.mes.qc CreatedTime = DateTime.Now.ToString() }; } - + /// /// 创建合格品单个标签DTO /// @@ -4152,7 +4232,7 @@ namespace ZR.Service.mes.qc CreatedTime = DateTime.Now.ToString() }; } - + /// /// 创建抛光品满箱标签DTO /// @@ -4179,7 +4259,7 @@ namespace ZR.Service.mes.qc CreatedTime = DateTime.Now.ToString() }; } - + /// /// 创建抛光品零头箱标签DTO /// @@ -4207,7 +4287,7 @@ namespace ZR.Service.mes.qc CreatedTime = DateTime.Now.ToString() }; } - + /// /// 创建抛光品单个标签DTO /// @@ -4234,7 +4314,7 @@ namespace ZR.Service.mes.qc CreatedTime = DateTime.Now.ToString() }; } - + /// /// 创建打磨品标签DTO /// From a4df709f06c9429072f8d612855d36ba1f57c63a Mon Sep 17 00:00:00 2001 From: git_rabbit Date: Thu, 12 Feb 2026 13:42:28 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E5=8C=85=E8=A3=85=E5=B7=A5=E4=BD=8D?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=90=88=E5=B9=B6=EF=BC=88=E6=B3=A8=E6=84=8F?= =?UTF-8?q?=E6=AD=A4=E4=BB=A3=E7=A0=81=E4=BB=85=E5=8A=9F=E8=83=BD=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E4=BA=86=E4=B8=80=E4=B8=8B=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...y-168e1cde-e622-4ff7-a1b4-6130c0cf779b.xml | 16 + ZR.Service/mes/qc/FirstFQCService.cs | 298 +++++++++++------- 2 files changed, 201 insertions(+), 113 deletions(-) create mode 100644 ZR.Admin.WebApi/DataProtection/key-168e1cde-e622-4ff7-a1b4-6130c0cf779b.xml diff --git a/ZR.Admin.WebApi/DataProtection/key-168e1cde-e622-4ff7-a1b4-6130c0cf779b.xml b/ZR.Admin.WebApi/DataProtection/key-168e1cde-e622-4ff7-a1b4-6130c0cf779b.xml new file mode 100644 index 00000000..8c5ec018 --- /dev/null +++ b/ZR.Admin.WebApi/DataProtection/key-168e1cde-e622-4ff7-a1b4-6130c0cf779b.xml @@ -0,0 +1,16 @@ + + + 2026-02-12T05:40:06.6830819Z + 2026-02-12T05:40:06.655139Z + 2026-05-13T05:40:06.655139Z + + + + + + + NCpSClOTA2Ukw8w2WJ8oXpw0xP6UPgALGnpWUcujYVjZht+UGKueBJnWKhzmFvUoX4WQiS0J8ie/rbUPGhGXIA== + + + + \ No newline at end of file diff --git a/ZR.Service/mes/qc/FirstFQCService.cs b/ZR.Service/mes/qc/FirstFQCService.cs index 91bfbb0e..964aa12c 100644 --- a/ZR.Service/mes/qc/FirstFQCService.cs +++ b/ZR.Service/mes/qc/FirstFQCService.cs @@ -38,7 +38,6 @@ namespace ZR.Service.mes.qc /// /// /// - public CheckItemTableDTO GetCheckItemTable_first(string workorderID) { CheckItemTableDTO checkItem = new CheckItemTableDTO(); @@ -159,7 +158,6 @@ namespace ZR.Service.mes.qc /// 首检结束时间 /// /// - public int WriteProcessFlow_first(string workorderID, DateTime time) { ProWorkordertimeStep step = new ProWorkordertimeStep(); @@ -179,7 +177,6 @@ namespace ZR.Service.mes.qc /// /// /// - public CheckItemTableDTO GetCheckItemTable_again(string workorderID) { CheckItemTableDTO checkItem = new CheckItemTableDTO(); @@ -298,7 +295,6 @@ namespace ZR.Service.mes.qc /// /// /// - public CheckItemTableDTO GetCheckItemTable_thirty(string workorderID) { CheckItemTableDTO checkItem = new CheckItemTableDTO(); @@ -441,7 +437,7 @@ namespace ZR.Service.mes.qc { it.FKInpectionId, it.FKWorkorderId, - it.InspectionModule + it.InspectionModule, }) .ToStorage(); @@ -458,8 +454,6 @@ namespace ZR.Service.mes.qc // scrap.ProductName = ""; // scrap.Number= 1; - - //} ////更新初检xiazi表 @@ -498,7 +492,7 @@ namespace ZR.Service.mes.qc { it.FkInpectionId, it.FkWorkorderId, - it.InspectionModule + it.InspectionModule, }) .ToStorage(); @@ -515,8 +509,6 @@ namespace ZR.Service.mes.qc // scrap.ProductName = ""; // scrap.Number= 1; - - //} ////更新初检xiazi表 @@ -555,17 +547,17 @@ namespace ZR.Service.mes.qc { it.FkInpectionId, it.FkWorkorderId, - it.InspectionModule + it.InspectionModule, }) .ToStorage(); x.AsInsertable.ExecuteCommandAsync(); //执行插入 x.AsUpdateable.UpdateColumns(it => new - { - it.UpdatedBy, - it.UpdatedTime, - it.Counter - }) + { + it.UpdatedBy, + it.UpdatedTime, + it.Counter, + }) .ExecuteCommandAsync(); //执行更新 ////更新初检报废表 @@ -578,8 +570,6 @@ namespace ZR.Service.mes.qc // scrap.ProductName = ""; // scrap.Number= 1; - - //} ////更新初检xiazi表 @@ -616,7 +606,6 @@ namespace ZR.Service.mes.qc //TODO 1. 处理首检 - //1.1 首检合格数=投入数-抛光数-打磨数-报废数 List qcFirstinspections = Context .Queryable() @@ -778,7 +767,6 @@ namespace ZR.Service.mes.qc /// /// /// - static double CalculatePercentage(int num1, int num2) { double percentage = ((double)num1 / num2) * 100; @@ -820,7 +808,7 @@ namespace ZR.Service.mes.qc FirstPassRate = 0.0, PolisheNumber = 0, ScrapNumber = 0, - DefectNumber = 0 + DefectNumber = 0, } ); ; @@ -903,9 +891,13 @@ namespace ZR.Service.mes.qc { Now_producting_Workorder_thirty = Now_producting_WorkorderList[0]; // 发送TCP消息 - if (Now_producting_Workorder_thirty != null && !string.IsNullOrEmpty(Now_producting_Workorder_thirty.FinishedPartNumber)) + if ( + Now_producting_Workorder_thirty != null + && !string.IsNullOrEmpty(Now_producting_Workorder_thirty.FinishedPartNumber) + ) { - string message = $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; + string message = + $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; _ = SendTcpMessageAsync(message); } return Now_producting_Workorder_thirty; @@ -915,7 +907,8 @@ namespace ZR.Service.mes.qc // 发送TCP消息 if (!string.IsNullOrEmpty(Now_producting_Workorder_thirty.FinishedPartNumber)) { - string message = $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; + string message = + $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; _ = SendTcpMessageAsync(message); } return Now_producting_Workorder_thirty; @@ -953,7 +946,11 @@ namespace ZR.Service.mes.qc // 等待服务器响应(可选) byte[] responseBuffer = new byte[4096]; - int bytesRead = await stream.ReadAsync(responseBuffer, 0, responseBuffer.Length); + int bytesRead = await stream.ReadAsync( + responseBuffer, + 0, + responseBuffer.Length + ); string response = Encoding.UTF8.GetString(responseBuffer, 0, bytesRead); _logger.LogInformation($"收到TCP服务器响应: {response}"); } @@ -1003,7 +1000,6 @@ namespace ZR.Service.mes.qc { // 已经是最后一个了没有 - return null; } else @@ -1051,7 +1047,6 @@ namespace ZR.Service.mes.qc { // 已经是最后一个了没有 - return null; } else @@ -1094,9 +1089,13 @@ namespace ZR.Service.mes.qc // 逻辑异常 Now_producting_Workorder_thirty = Now_producting_WorkorderList[0]; // 发送TCP消息 - if (Now_producting_Workorder_thirty != null && !string.IsNullOrEmpty(Now_producting_Workorder_thirty.FinishedPartNumber)) + if ( + Now_producting_Workorder_thirty != null + && !string.IsNullOrEmpty(Now_producting_Workorder_thirty.FinishedPartNumber) + ) { - string message = $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; + string message = + $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; _ = SendTcpMessageAsync(message); } return null; @@ -1110,9 +1109,13 @@ namespace ZR.Service.mes.qc { Now_producting_Workorder_thirty = Now_producting_WorkorderList[index + 1]; // 发送TCP消息 - if (Now_producting_Workorder_thirty != null && !string.IsNullOrEmpty(Now_producting_Workorder_thirty.FinishedPartNumber)) + if ( + Now_producting_Workorder_thirty != null + && !string.IsNullOrEmpty(Now_producting_Workorder_thirty.FinishedPartNumber) + ) { - string message = $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; + string message = + $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; _ = SendTcpMessageAsync(message); } return Now_producting_Workorder_thirty; @@ -1154,7 +1157,6 @@ namespace ZR.Service.mes.qc /// /// /// - public QcCurrentWorkorderDto GetcurrentWorkorder_previous_first() { //获取状态为1的生产工单列表 @@ -1201,7 +1203,6 @@ namespace ZR.Service.mes.qc /// /// /// - public QcCurrentWorkorderDto GetcurrentWorkorder_previous_again() { //获取状态为1的生产工单列表 @@ -1248,7 +1249,6 @@ namespace ZR.Service.mes.qc /// /// /// - public QcCurrentWorkorderDto GetcurrentWorkorder_previous_thirty() { //获取状态为1的生产工单列表 @@ -1276,9 +1276,13 @@ namespace ZR.Service.mes.qc // 逻辑异常 Now_producting_Workorder_thirty = Now_producting_WorkorderList[0]; // 发送TCP消息 - if (Now_producting_Workorder_thirty != null && !string.IsNullOrEmpty(Now_producting_Workorder_thirty.FinishedPartNumber)) + if ( + Now_producting_Workorder_thirty != null + && !string.IsNullOrEmpty(Now_producting_Workorder_thirty.FinishedPartNumber) + ) { - string message = $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; + string message = + $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; _ = SendTcpMessageAsync(message); } return null; @@ -1292,9 +1296,13 @@ namespace ZR.Service.mes.qc { Now_producting_Workorder_thirty = Now_producting_WorkorderList[index - 1]; // 发送TCP消息 - if (Now_producting_Workorder_thirty != null && !string.IsNullOrEmpty(Now_producting_Workorder_thirty.FinishedPartNumber)) + if ( + Now_producting_Workorder_thirty != null + && !string.IsNullOrEmpty(Now_producting_Workorder_thirty.FinishedPartNumber) + ) { - string message = $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; + string message = + $"shgx/cx/gz/{Now_producting_Workorder_thirty.FinishedPartNumber}"; _ = SendTcpMessageAsync(message); } return Now_producting_Workorder_thirty; @@ -1514,7 +1522,6 @@ namespace ZR.Service.mes.qc /// /// /// - public int CalculatePackagingInvestment(string workorder_id) { int OnePassNumber = 0; @@ -2811,7 +2818,6 @@ namespace ZR.Service.mes.qc #endregion - #region 三检 #region 三捡-抛光 QcQualityStatisticsFinal final1 = new QcQualityStatisticsFinal(); @@ -2849,7 +2855,8 @@ namespace ZR.Service.mes.qc .Queryable() .Where(it => it.FkWorkorderId == workorderID) .Where(it => SqlFunc.Contains(it.FkInpectionId, "_1_")) - .Sum(it => it.Counter) ?? 0; + .Sum(it => it.Counter) + ?? 0; if (finalrecordList != null && finalrecordList.Count > 0) { @@ -3868,7 +3875,6 @@ namespace ZR.Service.mes.qc //XXX:修改合格数公式:包装数 // total2.QualifiedNumber = (again2.RequireNumber ?? 0) - qualifiedNumber_No_all_total; - // 总报表-抛光记录插入 total1.QualifiedNumber = final1.QualifiedNumber; if (total1.RequireNumber == 0) @@ -3910,7 +3916,6 @@ namespace ZR.Service.mes.qc // total2.DamoTotal = damo_total_again + damo_total_final; // total2.BaofeiTotal = baofei_total_again3 + baofei_total_final; - var x_total_2 = Context .Storageable(total2) .WhereColumns(it => new { it.WorkorderId, it.Remark2 }) @@ -3938,7 +3943,6 @@ namespace ZR.Service.mes.qc // total3.DamoTotal = damo_total_again + damo_total_final; // total3.BaofeiTotal = baofei_total_again3 + baofei_total_final; - var x_total_3 = Context .Storageable(total3) .WhereColumns(it => new { it.WorkorderId, it.Remark2 }) @@ -3950,7 +3954,6 @@ namespace ZR.Service.mes.qc #endregion - //TODO 20241023 不再变动抛光盘点后的数据 try @@ -3966,96 +3969,130 @@ namespace ZR.Service.mes.qc string polishLabelPath = "D:\\RIZO\\label\\抛光送货单.btw"; string polishingLabelPath = "D:\\RIZO\\label\\打磨送货单.btw"; //TODO 20251027 检查是否存在产线产品托盘配置 - WmMaterialPackage packageConfig = Context.Queryable() + WmMaterialPackage packageConfig = Context + .Queryable() .Where(it => it.RecordType == "零件") .Where(it => it.PartNumber == first.FinishedPartNumber) .First(); //TODO 20251027 计算合格数是否超出合格托盘 - if (packageConfig != null && packageConfig.PackageProductionQualifiedPalletNum != null) + if ( + packageConfig != null + && packageConfig.PackageProductionQualifiedPalletNum != null + ) { // 合格数超额分段出标签 if (qualifiedNumber > packageConfig.PackageProductionQualifiedPalletNum) { // 分批次出多个合格品满箱标签和零头箱标签 - int qualifiedPalletCapacity = packageConfig.PackageProductionQualifiedPalletNum.Value; + int qualifiedPalletCapacity = packageConfig + .PackageProductionQualifiedPalletNum + .Value; int fullPalletCount = qualifiedNumber / qualifiedPalletCapacity; int remainderCount = qualifiedNumber % qualifiedPalletCapacity; // 出满箱标签 for (int i = 1; i <= fullPalletCount; i++) { - PrintDeliveryNoteDto qualifiedFullPalletDto = CreateQualifiedFullPalletLabelDto(first, qualifiedPalletCapacity, i); + PrintDeliveryNoteDto qualifiedFullPalletDto = + CreateQualifiedFullPalletLabelDto( + first, + qualifiedPalletCapacity, + i + ); SendMqttLabelMessage(mqttTopic, qualifiedFullPalletDto); } // 出零头箱标签 if (remainderCount > 0) { - PrintDeliveryNoteDto qualifiedRemainderDto = CreateQualifiedRemainderLabelDto(first, remainderCount, fullPalletCount); + PrintDeliveryNoteDto qualifiedRemainderDto = + CreateQualifiedRemainderLabelDto( + first, + remainderCount, + fullPalletCount + ); SendMqttLabelMessage(mqttTopic, qualifiedRemainderDto); } } else { // 正常出单个标签 - PrintDeliveryNoteDto qualifiedSingleLabelDto = CreateQualifiedSingleLabelDto(first, first.QualifiedNumber.Value); + PrintDeliveryNoteDto qualifiedSingleLabelDto = + CreateQualifiedSingleLabelDto(first, first.QualifiedNumber.Value); SendMqttLabelMessage(mqttTopic, qualifiedSingleLabelDto); } } else { // 没有配置时使用默认的单个标签打印 - PrintDeliveryNoteDto qualifiedSingleLabelDto = CreateQualifiedSingleLabelDto(first, first.QualifiedNumber.Value); + PrintDeliveryNoteDto qualifiedSingleLabelDto = + CreateQualifiedSingleLabelDto(first, first.QualifiedNumber.Value); SendMqttLabelMessage(mqttTopic, qualifiedSingleLabelDto); } - if (packageConfig != null && packageConfig.PackageProductionPolishPalletNum != null) + if ( + packageConfig != null + && packageConfig.PackageProductionPolishPalletNum != null + ) { // 抛光数超额分段 if (paoguangTotal > packageConfig.PackageProductionPolishPalletNum) { // 分批次出多个抛光品满箱标签和零头箱标签 - int polishPalletCapacity = packageConfig.PackageProductionPolishPalletNum.Value; + int polishPalletCapacity = packageConfig + .PackageProductionPolishPalletNum + .Value; int fullPalletCount = paoguangTotal / polishPalletCapacity; int remainderCount = paoguangTotal % polishPalletCapacity; // 出满箱标签 for (int i = 1; i <= fullPalletCount; i++) { - PrintDeliveryNoteDto polishFullPalletDto = CreatePolishFullPalletLabelDto(first, polishPalletCapacity, i); + PrintDeliveryNoteDto polishFullPalletDto = + CreatePolishFullPalletLabelDto(first, polishPalletCapacity, i); SendMqttLabelMessage(mqttTopic, polishFullPalletDto); } // 出零头箱标签 if (remainderCount > 0) { - PrintDeliveryNoteDto polishRemainderDto = CreatePolishRemainderLabelDto(first, remainderCount, fullPalletCount); + PrintDeliveryNoteDto polishRemainderDto = + CreatePolishRemainderLabelDto( + first, + remainderCount, + fullPalletCount + ); SendMqttLabelMessage(mqttTopic, polishRemainderDto); } } else { // 正常出单个标签 - PrintDeliveryNoteDto polishSingleLabelDto = CreatePolishSingleLabelDto(first, first.PaoguangTotal.Value); + PrintDeliveryNoteDto polishSingleLabelDto = CreatePolishSingleLabelDto( + first, + first.PaoguangTotal.Value + ); SendMqttLabelMessage(mqttTopic, polishSingleLabelDto); } } else { // 没有配置时使用默认的单个标签打印 - PrintDeliveryNoteDto polishSingleLabelDto = CreatePolishSingleLabelDto(first, first.PaoguangTotal.Value); + PrintDeliveryNoteDto polishSingleLabelDto = CreatePolishSingleLabelDto( + first, + first.PaoguangTotal.Value + ); SendMqttLabelMessage(mqttTopic, polishSingleLabelDto); } - // 使用辅助方法创建打磨标签 - PrintDeliveryNoteDto polishingLabelDto = CreatePolishingLabelDto(first, first.DamoTotal.Value); + PrintDeliveryNoteDto polishingLabelDto = CreatePolishingLabelDto( + first, + first.DamoTotal.Value + ); SendMqttLabelMessage(mqttTopic, polishingLabelDto); } - catch (Exception) - { - - } + catch (Exception) { } return 1; // 以下代码暂时停用 @@ -4064,17 +4101,19 @@ namespace ZR.Service.mes.qc { // 1.抛光品入库 WmPolishInventoryService wmPolishInventoryService = new(); - WmPolishInventory warehousingInfo = - new() - { - Partnumber = workorder_item.FinishedPartNumber, - WorkOrder = workorder_item.ClientWorkorder, - Type = workorder_item.Remark1.Contains("返工") ? 2 : 1, - Quantity = paoguang_by_first + paoguang_final, - ActionTime = DateTime.Now.ToLocalTime(), - CreatedBy = "包装" + team + "组", - Remark = "产线抛光件,自动入库。来源工单号:[" + workorder_item.ClientWorkorder + "]" - }; + WmPolishInventory warehousingInfo = new() + { + Partnumber = workorder_item.FinishedPartNumber, + WorkOrder = workorder_item.ClientWorkorder, + Type = workorder_item.Remark1.Contains("返工") ? 2 : 1, + Quantity = paoguang_by_first + paoguang_final, + ActionTime = DateTime.Now.ToLocalTime(), + CreatedBy = "包装" + team + "组", + Remark = + "产线抛光件,自动入库。来源工单号:[" + + workorder_item.ClientWorkorder + + "]", + }; wmPolishInventoryService.DoWmPolishWarehousing(warehousingInfo); // 2.成品入一次合格品库 // 合格品检查是否是门把手或倒车雷达,是进入成品库(仅出库),不是进入一次合格品库 @@ -4090,7 +4129,7 @@ namespace ZR.Service.mes.qc "B02", "V71", "T1EJ ", - "倒车雷达" + "倒车雷达", }; var isDoorknobCheck = Expressionable.Create(); foreach (string checkStr in checkStrArray) @@ -4108,22 +4147,23 @@ namespace ZR.Service.mes.qc if (!isDoorknob) { WmOneTimeInventoryService oneTimeService = new(); - WmOneTimeInventory wmOneTimeInventoryWarehousing = - new() - { - Partnumber = workorder_item.FinishedPartNumber, - WorkOrder = workorder_item.ClientWorkorder, - Type = workorder_item.Remark1.Contains("返工") ? 2 : 1, - Quantity = total3.QualifiedNumber, - CreatedBy = "包装" + team + "组", - ActionTime = DateTime.Now.ToLocalTime(), - Remark = - "包装合格品入库,合格数:" - + total3.QualifiedNumber - + "、工单号:" - + workorder_item.ClientWorkorder - ?? "未填写工单号" + "。记录时间:" + DateTime.Now.ToLocalTime().ToString() - }; + WmOneTimeInventory wmOneTimeInventoryWarehousing = new() + { + Partnumber = workorder_item.FinishedPartNumber, + WorkOrder = workorder_item.ClientWorkorder, + Type = workorder_item.Remark1.Contains("返工") ? 2 : 1, + Quantity = total3.QualifiedNumber, + CreatedBy = "包装" + team + "组", + ActionTime = DateTime.Now.ToLocalTime(), + Remark = + "包装合格品入库,合格数:" + + total3.QualifiedNumber + + "、工单号:" + + workorder_item.ClientWorkorder + ?? "未填写工单号" + + "。记录时间:" + + DateTime.Now.ToLocalTime().ToString(), + }; oneTimeService.DoWmOneTimeWarehousing(wmOneTimeInventoryWarehousing); } } @@ -4154,7 +4194,11 @@ namespace ZR.Service.mes.qc /// /// 创建合格品满箱标签DTO /// - private PrintDeliveryNoteDto CreateQualifiedFullPalletLabelDto(QcQualityStatisticsFirst first, int qualifiedPalletNum, int batchIndex) + private PrintDeliveryNoteDto CreateQualifiedFullPalletLabelDto( + QcQualityStatisticsFirst first, + int qualifiedPalletNum, + int batchIndex + ) { return new PrintDeliveryNoteDto { @@ -4172,16 +4216,21 @@ namespace ZR.Service.mes.qc ProductionTime = first.WorkorderId, BatchCode = first.WorkorderId, PackageNum = qualifiedPalletNum, - LabelCode = $"Type=DeNoHG^ItemNumber={first.FinishedPartNumber}^Order={first.WorkorderId}^Qty={qualifiedPalletNum}^Batch={batchIndex}", + LabelCode = + $"Type=DeNoHG^ItemNumber={first.FinishedPartNumber}^Order={first.WorkorderId}^Qty={qualifiedPalletNum}^Batch={batchIndex}", LabelType = 1, - CreatedTime = DateTime.Now.ToString() + CreatedTime = DateTime.Now.ToString(), }; } /// /// 创建合格品零头箱标签DTO /// - private PrintDeliveryNoteDto CreateQualifiedRemainderLabelDto(QcQualityStatisticsFirst first, int remainderCount, int fullPalletCount) + private PrintDeliveryNoteDto CreateQualifiedRemainderLabelDto( + QcQualityStatisticsFirst first, + int remainderCount, + int fullPalletCount + ) { int remainderBatchIndex = fullPalletCount + 1; return new PrintDeliveryNoteDto @@ -4200,16 +4249,20 @@ namespace ZR.Service.mes.qc ProductionTime = first.WorkorderId, BatchCode = first.WorkorderId, PackageNum = remainderCount, - LabelCode = $"Type=DeNoHG^ItemNumber={first.FinishedPartNumber}^Order={first.WorkorderId}^Qty={remainderCount}^Batch={remainderBatchIndex}_remainder", + LabelCode = + $"Type=DeNoHG^ItemNumber={first.FinishedPartNumber}^Order={first.WorkorderId}^Qty={remainderCount}^Batch={remainderBatchIndex}_remainder", LabelType = 1, - CreatedTime = DateTime.Now.ToString() + CreatedTime = DateTime.Now.ToString(), }; } /// /// 创建合格品单个标签DTO /// - private PrintDeliveryNoteDto CreateQualifiedSingleLabelDto(QcQualityStatisticsFirst first, int qualifiedNumber) + private PrintDeliveryNoteDto CreateQualifiedSingleLabelDto( + QcQualityStatisticsFirst first, + int qualifiedNumber + ) { return new PrintDeliveryNoteDto { @@ -4227,16 +4280,21 @@ namespace ZR.Service.mes.qc ProductionTime = first.WorkorderId, BatchCode = first.WorkorderId, PackageNum = qualifiedNumber, - LabelCode = $"Type=DeNoHG^ItemNumber={first.FinishedPartNumber}^Order={first.WorkorderId}^Qty={qualifiedNumber}", + LabelCode = + $"Type=DeNoHG^ItemNumber={first.FinishedPartNumber}^Order={first.WorkorderId}^Qty={qualifiedNumber}", LabelType = 1, - CreatedTime = DateTime.Now.ToString() + CreatedTime = DateTime.Now.ToString(), }; } /// /// 创建抛光品满箱标签DTO /// - private PrintDeliveryNoteDto CreatePolishFullPalletLabelDto(QcQualityStatisticsFirst first, int polishPalletNum, int batchIndex) + private PrintDeliveryNoteDto CreatePolishFullPalletLabelDto( + QcQualityStatisticsFirst first, + int polishPalletNum, + int batchIndex + ) { return new PrintDeliveryNoteDto { @@ -4254,16 +4312,21 @@ namespace ZR.Service.mes.qc ProductionTime = first.WorkorderId, BatchCode = first.WorkorderId, PackageNum = polishPalletNum, - LabelCode = $"Type=DeNoPG^ItemNumber={first.FinishedPartNumber}^Order={first.WorkorderId}^Qty={polishPalletNum}^Batch={batchIndex}", + LabelCode = + $"Type=DeNoPG^ItemNumber={first.FinishedPartNumber}^Order={first.WorkorderId}^Qty={polishPalletNum}^Batch={batchIndex}", LabelType = 1, - CreatedTime = DateTime.Now.ToString() + CreatedTime = DateTime.Now.ToString(), }; } /// /// 创建抛光品零头箱标签DTO /// - private PrintDeliveryNoteDto CreatePolishRemainderLabelDto(QcQualityStatisticsFirst first, int remainderCount, int fullPalletCount) + private PrintDeliveryNoteDto CreatePolishRemainderLabelDto( + QcQualityStatisticsFirst first, + int remainderCount, + int fullPalletCount + ) { int remainderBatchIndex = fullPalletCount + 1; return new PrintDeliveryNoteDto @@ -4282,16 +4345,20 @@ namespace ZR.Service.mes.qc ProductionTime = first.WorkorderId, BatchCode = first.WorkorderId, PackageNum = remainderCount, - LabelCode = $"Type=DeNoPG^ItemNumber={first.FinishedPartNumber}^Order={first.WorkorderId}^Qty={remainderCount}^Batch={remainderBatchIndex}_remainder", + LabelCode = + $"Type=DeNoPG^ItemNumber={first.FinishedPartNumber}^Order={first.WorkorderId}^Qty={remainderCount}^Batch={remainderBatchIndex}_remainder", LabelType = 1, - CreatedTime = DateTime.Now.ToString() + CreatedTime = DateTime.Now.ToString(), }; } /// /// 创建抛光品单个标签DTO /// - private PrintDeliveryNoteDto CreatePolishSingleLabelDto(QcQualityStatisticsFirst first, int polishTotal) + private PrintDeliveryNoteDto CreatePolishSingleLabelDto( + QcQualityStatisticsFirst first, + int polishTotal + ) { return new PrintDeliveryNoteDto { @@ -4309,16 +4376,20 @@ namespace ZR.Service.mes.qc ProductionTime = first.WorkorderId, BatchCode = first.WorkorderId, PackageNum = polishTotal, - LabelCode = $"Type=DeNoPG^ItemNumber={first.FinishedPartNumber}^Order={first.WorkorderId}^Qty={polishTotal}", + LabelCode = + $"Type=DeNoPG^ItemNumber={first.FinishedPartNumber}^Order={first.WorkorderId}^Qty={polishTotal}", LabelType = 1, - CreatedTime = DateTime.Now.ToString() + CreatedTime = DateTime.Now.ToString(), }; } /// /// 创建打磨品标签DTO /// - private PrintDeliveryNoteDto CreatePolishingLabelDto(QcQualityStatisticsFirst first, int polishingTotal) + private PrintDeliveryNoteDto CreatePolishingLabelDto( + QcQualityStatisticsFirst first, + int polishingTotal + ) { return new PrintDeliveryNoteDto { @@ -4336,9 +4407,10 @@ namespace ZR.Service.mes.qc ProductionTime = first.WorkorderId, BatchCode = first.WorkorderId, PackageNum = polishingTotal, - LabelCode = $"Type=DeNoDM^ItemNumber={first.FinishedPartNumber}^Order={first.WorkorderId}^Qty={polishingTotal}", + LabelCode = + $"Type=DeNoDM^ItemNumber={first.FinishedPartNumber}^Order={first.WorkorderId}^Qty={polishingTotal}", LabelType = 1, - CreatedTime = DateTime.Now.ToString() + CreatedTime = DateTime.Now.ToString(), }; } }