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/.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/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.Admin.WebApi/Program.cs b/ZR.Admin.WebApi/Program.cs
index 23fe84a4..af097c33 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.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/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/FirstFQCService.cs b/ZR.Service/mes/qc/FirstFQCService.cs
index 5886fc89..964aa12c 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;
@@ -36,7 +38,6 @@ namespace ZR.Service.mes.qc
///
///
///
-
public CheckItemTableDTO GetCheckItemTable_first(string workorderID)
{
CheckItemTableDTO checkItem = new CheckItemTableDTO();
@@ -157,7 +158,6 @@ namespace ZR.Service.mes.qc
/// 首检结束时间
///
///
-
public int WriteProcessFlow_first(string workorderID, DateTime time)
{
ProWorkordertimeStep step = new ProWorkordertimeStep();
@@ -177,7 +177,6 @@ namespace ZR.Service.mes.qc
///
///
///
-
public CheckItemTableDTO GetCheckItemTable_again(string workorderID)
{
CheckItemTableDTO checkItem = new CheckItemTableDTO();
@@ -296,7 +295,6 @@ namespace ZR.Service.mes.qc
///
///
///
-
public CheckItemTableDTO GetCheckItemTable_thirty(string workorderID)
{
CheckItemTableDTO checkItem = new CheckItemTableDTO();
@@ -439,7 +437,7 @@ namespace ZR.Service.mes.qc
{
it.FKInpectionId,
it.FKWorkorderId,
- it.InspectionModule
+ it.InspectionModule,
})
.ToStorage();
@@ -456,8 +454,6 @@ namespace ZR.Service.mes.qc
// scrap.ProductName = "";
// scrap.Number= 1;
-
-
//}
////更新初检xiazi表
@@ -496,7 +492,7 @@ namespace ZR.Service.mes.qc
{
it.FkInpectionId,
it.FkWorkorderId,
- it.InspectionModule
+ it.InspectionModule,
})
.ToStorage();
@@ -513,8 +509,6 @@ namespace ZR.Service.mes.qc
// scrap.ProductName = "";
// scrap.Number= 1;
-
-
//}
////更新初检xiazi表
@@ -553,7 +547,7 @@ namespace ZR.Service.mes.qc
{
it.FkInpectionId,
it.FkWorkorderId,
- it.InspectionModule
+ it.InspectionModule,
})
.ToStorage();
@@ -562,7 +556,7 @@ namespace ZR.Service.mes.qc
{
it.UpdatedBy,
it.UpdatedTime,
- it.Counter
+ it.Counter,
})
.ExecuteCommandAsync(); //执行更新
@@ -576,8 +570,6 @@ namespace ZR.Service.mes.qc
// scrap.ProductName = "";
// scrap.Number= 1;
-
-
//}
////更新初检xiazi表
@@ -614,7 +606,6 @@ namespace ZR.Service.mes.qc
//TODO 1. 处理首检
-
//1.1 首检合格数=投入数-抛光数-打磨数-报废数
List qcFirstinspections = Context
.Queryable()
@@ -776,7 +767,6 @@ namespace ZR.Service.mes.qc
///
///
///
-
static double CalculatePercentage(int num1, int num2)
{
double percentage = ((double)num1 / num2) * 100;
@@ -818,7 +808,7 @@ namespace ZR.Service.mes.qc
FirstPassRate = 0.0,
PolisheNumber = 0,
ScrapNumber = 0,
- DefectNumber = 0
+ DefectNumber = 0,
}
);
;
@@ -900,14 +890,79 @@ 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}");
+ }
+ }
+
///
/// 获取下一个生产工单 一检
///
@@ -945,7 +1000,6 @@ namespace ZR.Service.mes.qc
{
// 已经是最后一个了没有
-
return null;
}
else
@@ -993,7 +1047,6 @@ namespace ZR.Service.mes.qc
{
// 已经是最后一个了没有
-
return null;
}
else
@@ -1035,18 +1088,36 @@ 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;
}
}
@@ -1086,7 +1157,6 @@ namespace ZR.Service.mes.qc
///
///
///
-
public QcCurrentWorkorderDto GetcurrentWorkorder_previous_first()
{
//获取状态为1的生产工单列表
@@ -1133,7 +1203,6 @@ namespace ZR.Service.mes.qc
///
///
///
-
public QcCurrentWorkorderDto GetcurrentWorkorder_previous_again()
{
//获取状态为1的生产工单列表
@@ -1180,7 +1249,6 @@ namespace ZR.Service.mes.qc
///
///
///
-
public QcCurrentWorkorderDto GetcurrentWorkorder_previous_thirty()
{
//获取状态为1的生产工单列表
@@ -1207,6 +1275,16 @@ 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 +1295,16 @@ 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;
}
}
@@ -1434,7 +1522,6 @@ namespace ZR.Service.mes.qc
///
///
///
-
public int CalculatePackagingInvestment(string workorder_id)
{
int OnePassNumber = 0;
@@ -2731,7 +2818,6 @@ namespace ZR.Service.mes.qc
#endregion
-
#region 三检
#region 三捡-抛光
QcQualityStatisticsFinal final1 = new QcQualityStatisticsFinal();
@@ -2769,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)
{
@@ -3788,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)
@@ -3830,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 })
@@ -3858,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 })
@@ -3870,7 +3954,6 @@ namespace ZR.Service.mes.qc
#endregion
-
//TODO 20241023 不再变动抛光盘点后的数据
try
@@ -3886,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);
- SendMqttLabelMessage(mqttTopic, qualifiedSingleLabelDto);
- }
+ {
+ // 没有配置时使用默认的单个标签打印
+ 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);
- SendMqttLabelMessage(mqttTopic, polishSingleLabelDto);
- }
-
+ {
+ // 没有配置时使用默认的单个标签打印
+ 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;
// 以下代码暂时停用
@@ -3984,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.成品入一次合格品库
// 合格品检查是否是门把手或倒车雷达,是进入成品库(仅出库),不是进入一次合格品库
@@ -4010,7 +4129,7 @@ namespace ZR.Service.mes.qc
"B02",
"V71",
"T1EJ ",
- "倒车雷达"
+ "倒车雷达",
};
var isDoorknobCheck = Expressionable.Create();
foreach (string checkStr in checkStrArray)
@@ -4028,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);
}
}
@@ -4054,7 +4174,7 @@ namespace ZR.Service.mes.qc
}
return 0;
}
-
+
///
/// 发送MQTT标签打印消息
///
@@ -4070,11 +4190,15 @@ namespace ZR.Service.mes.qc
)
.Wait();
}
-
+
///
/// 创建合格品满箱标签DTO
///
- private PrintDeliveryNoteDto CreateQualifiedFullPalletLabelDto(QcQualityStatisticsFirst first, int qualifiedPalletNum, int batchIndex)
+ private PrintDeliveryNoteDto CreateQualifiedFullPalletLabelDto(
+ QcQualityStatisticsFirst first,
+ int qualifiedPalletNum,
+ int batchIndex
+ )
{
return new PrintDeliveryNoteDto
{
@@ -4092,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
@@ -4120,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
{
@@ -4147,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
{
@@ -4174,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
@@ -4202,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
{
@@ -4229,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
{
@@ -4256,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(),
};
}
}
diff --git a/ZR.Service/mes/qc/backend/QcBackEndService.cs b/ZR.Service/mes/qc/backend/QcBackEndService.cs
index c8c8eccd..1627f1b4 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,188 @@ namespace ZR.Service.Business
return Guid.NewGuid().ToString("N").Substring(0, 10); // Generate a 10-character unique ID
}
+ ///
+ /// 发送标签打印MQTT消息
+ ///
+ /// 工单信息
+ /// 标签类型:1-抛光,2-打磨
+ /// 数量
+ ///
+ /// 发送标签打印MQTT消息
+ ///
+ /// 工单信息
+ /// 标签类型:1-抛光,2-打磨
+ /// 数量
+ private void SendLabelPrintMqttMessage(QcBackEndServiceWorkorder workorder, int labelType, int quantity)
+ {
+ try
+ {
+ if (quantity <= 0)
+ {
+ return;
+ }
+
+ // 1. 基本配置
+ string mqttTopic = "shgg_mes/backEnd/label_print/print/PGDM";
+ string labelCode = labelType == 1 ? "Type=DeNoPG" : "Type=DeNoDM";
+ string path = labelType == 1 ? "C:\\Program Files\\MES\\label\\送货单\\抛光送货单.btw" : "C:\\Program Files\\MES\\label\\送货单\\打磨送货单.btw";
+ string name = labelType == 1 ? "后道抛光送货单标签打印" : "后道打磨送货单标签打印";
+
+ // 2. 抛光标签特殊处理:检查托盘配置
+ if (labelType == 1)
+ {
+ // 查询零件的托盘配置
+ WmMaterialPackage packageConfig = Context.Queryable()
+ .Where(it => it.RecordType == "零件")
+ .Where(it => it.PartNumber == workorder.PartNumber)
+ .First();
+
+ // 检查是否有后道抛光托盘配置
+ 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)
+ {
+ // 记录异常但不影响主流程
+ _logger.LogError(ex, "发送后道标签打印MQTT消息失败");
+ }
+ }
+
+ ///
+ /// 分批次打印标签
+ ///
+ /// 工单信息
+ /// 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 bb374ae2..2f1d53cc 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,178 @@ 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;
+ }
+
+ // 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打磨送货单标签打印";
+
+ // 2. 抛光标签特殊处理:检查托盘配置
+ if (labelType == 1)
+ {
+ // 查询零件的托盘配置
+ WmMaterialPackage packageConfig = Context.Queryable()
+ .Where(it => it.RecordType == "零件")
+ .Where(it => it.PartNumber == workorder.PartNumber)
+ .First();
+
+ // 检查是否有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)
+ {
+ // 记录异常但不影响主流程
+ Console.WriteLine($"发送标签打印MQTT消息失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 分批次打印标签
+ ///
+ /// 工单信息
+ /// 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()
+ };
+ }
+
}
}
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}";
+ }
+ }
+}
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