This commit is contained in:
XingCheng3
2026-05-26 09:41:24 +08:00
commit dff0156cdd
1329 changed files with 88153 additions and 0 deletions

View File

@@ -0,0 +1,360 @@
using DataLinkMesWork1;
using MesServerWork;
using MisDataFunDll;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
namespace MesServerFunctions
{
partial class FunctionMES
{
private const string ManualStaticOutOpName = "OP431";
private const string ManualStaticPadTopic = "OP431PAD";
private const decimal DefaultManualStaticMinutes = 30m;
private const string ManualStaticLocation = "777777";
private const string ManualStaticOperator = "PAD";
private static readonly object ManualStaticMinutesLocker = new object();
private static readonly Dictionary<string, decimal> ManualStaticMinutesByEngine = new Dictionary<string, decimal>();
private class ManualStaticOutProduct
{
public string EngineID { get; set; }
public string OrderForm { get; set; }
public string EngineType { get; set; }
public int EngineTypeID { get; set; }
}
private class ManualStaticOutData
{
public string SourceOpName { get; set; }
public DateTime StartTime { get; set; }
public DateTime FinishTime { get; set; }
public decimal Minutes { get; set; }
public int QualityMask { get; set; }
}
private bool TryGetManualStaticOutProduct(string engineID, out ManualStaticOutProduct product, out string message)
{
product = null;
message = "";
if (string.IsNullOrWhiteSpace(engineID))
{
message = "产品码为空";
return false;
}
MisDataFun.Moby_Select_PDC(engineID, out string orderForm, out string engineType, out int engineTypeID);
if (engineTypeID <= 0 || string.IsNullOrWhiteSpace(engineType))
{
message = "未查询到产品执行信息:" + engineID;
return false;
}
product = new ManualStaticOutProduct
{
EngineID = engineID.Trim(),
OrderForm = orderForm,
EngineType = engineType,
EngineTypeID = engineTypeID
};
return true;
}
private bool TryGetManualStaticStartTime(string engineID, out string sourceOpName, out DateTime startTime, out string message)
{
sourceOpName = "";
startTime = DateTime.MinValue;
message = "";
try
{
// 取 OP400/OP410/OP420 最后一条有效离开记录作为常温静置开始时间。
string procedureName = "OP431手动静置出库_前序离开时间_查询";
SqlParameter[] sqlParameters = new SqlParameter[1];
sqlParameters[0] = new SqlParameter("@发动机号", engineID);
DataAccess.ExecuteStoredProcedure(procedureName, ref sqlParameters, out DataTable dt, out string errorMessage);
if (!string.IsNullOrWhiteSpace(errorMessage))
{
message = "查询前序出站时间失败:" + errorMessage;
return false;
}
if (dt == null || dt.Rows.Count == 0)
{
message = "未查询到 OP400/OP410/OP420 前序出站记录";
return false;
}
sourceOpName = Convert.ToString(dt.Rows[0]["工位号"]);
startTime = Convert.ToDateTime(dt.Rows[0]["开始静置时间"]);
return true;
}
catch (Exception err)
{
message = "查询前序出站时间失败:" + err.Message;
return false;
}
}
private bool TryBuildManualStaticOutData(string engineID, int qualityMask, out ManualStaticOutData staticOutData, out string message)
{
staticOutData = null;
message = "";
if (!TryGetManualStaticStartTime(engineID, out string sourceOpName, out DateTime startTime, out message))
{
return false;
}
DateTime finishTime = DateTime.Now;
decimal minutes = Math.Round(Convert.ToDecimal((finishTime - startTime).TotalMinutes), 2);
staticOutData = new ManualStaticOutData
{
SourceOpName = sourceOpName,
StartTime = startTime,
FinishTime = finishTime,
Minutes = minutes,
QualityMask = NormalizeManualStaticQualityMask(qualityMask)
};
return true;
}
private int NormalizeManualStaticQualityMask(int qualityMask)
{
return qualityMask == 1 ? 1 : 2;
}
private bool IsManualStaticTimeEnough(ManualStaticOutData staticOutData, decimal minStaticMinutes, out string message)
{
message = "";
if (staticOutData.Minutes < minStaticMinutes)
{
message = "静置时间不足 " + minStaticMinutes.ToString("0.##") + " 分钟,当前已静置 " + staticOutData.Minutes + " 分钟";
return false;
}
return true;
}
private bool WriteManualStaticOutQualityData(string opName, string engineID, ManualStaticOutData data, out string message)
{
message = "";
int idTagCf = 0;
if (!TryGetManualStaticMinutesForProduct(engineID, out decimal rememberedMinStaticMinutes))
{
message = "未找到PAD确认的最小静置标准请在PAD重新确认上线后再保存" + engineID;
return false;
}
string minStaticMinutes = rememberedMinStaticMinutes.ToString("0.##");
// OP431 的静置数据由 Function 直接落库,不再通过 OnlineCheckData 做 HTTP 自调用。
SqlParameter[] indexParams = new SqlParameter[6];
indexParams[0] = new SqlParameter("@EngineID", engineID);
indexParams[1] = new SqlParameter("@工位号", opName);
indexParams[2] = new SqlParameter("@操作者工号", ManualStaticOperator);
indexParams[3] = new SqlParameter("@扫码时间", data.FinishTime);
indexParams[4] = new SqlParameter("@合格标志", data.QualityMask);
indexParams[5] = new SqlParameter("@Id_tagCF", idTagCf);
indexParams[5].Direction = ParameterDirection.Output;
DataAccess.ExecuteStoredProcedure("测量数据合格索引_增加_测试设备", ref indexParams, out string errorMessage);
if (!string.IsNullOrWhiteSpace(errorMessage))
{
message = "写入静置质量索引失败:" + errorMessage;
return false;
}
idTagCf = Convert.ToInt32(indexParams[5].Value.ToString());
if (idTagCf <= 0)
{
message = "写入静置质量索引失败:未生成 Id_tagCF";
return false;
}
object[,] detailRows = new object[,]
{
{ "OP431_M0001_001", "开始静置时间", "min", "1", "60", minStaticMinutes, data.StartTime.ToString("yyyy-MM-dd HH:mm:ss"), data.QualityMask },
{ "OP431_M0001_002", "静置完成时间", "min", "1", "60", minStaticMinutes, data.FinishTime.ToString("yyyy-MM-dd HH:mm:ss"), data.QualityMask },
{ "OP431_M0001_003", "静置时间差", "min", "1", "60", minStaticMinutes, data.Minutes.ToString("0.##"), data.QualityMask },
{ "OP431_M0001_004", "静置库位号", "静置库位", "-1", "-1", "-1", ManualStaticLocation, data.QualityMask }
};
for (int i = 0; i < detailRows.GetLength(0); i++)
{
SqlParameter[] detailParams = new SqlParameter[]
{
new SqlParameter("@Id_tagCF", idTagCf),
new SqlParameter("@EngineID", engineID),
new SqlParameter("@TagID", detailRows[i, 0]),
new SqlParameter("@TagValue", detailRows[i, 6]),
new SqlParameter("@IsGoodBad", detailRows[i, 7]),
new SqlParameter("@工位号", opName),
new SqlParameter("@理论值", detailRows[i, 3]),
new SqlParameter("@上限值", detailRows[i, 4]),
new SqlParameter("@下限值", detailRows[i, 5]),
new SqlParameter("@测量项目", detailRows[i, 1]),
new SqlParameter("@测量单位", detailRows[i, 2])
};
DataAccess.ExecuteStoredProcedure("测量数据合格_增加_测试设备", ref detailParams, out errorMessage);
if (!string.IsNullOrWhiteSpace(errorMessage))
{
message = "写入静置质量明细失败:" + errorMessage;
return false;
}
}
return true;
}
private bool CheckManualStaticPadPrecondition(string opName, out string message)
{
message = "";
MIS_BASE.Read_WorkStart(opName, out bool workStart);
if (!workStart)
{
message = "当前无托盘到位信号,不允许扫码确认";
return false;
}
MIS_BASE.Read_PartLoad(opName, out bool partLoad);
if (!partLoad)
{
message = "PLC尚未申请上线不允许扫码确认";
return false;
}
return true;
}
private bool ConfirmManualStaticOutProduct(string opName, string engineID, decimal minStaticMinutes, out string message)
{
message = "";
// PAD 确认上线时必须重新校验托盘和 PLC 申请状态,不能复用查询时的旧结果。
if (!CheckManualStaticPadPrecondition(opName, out message))
{
return false;
}
if (!TryGetManualStaticOutProduct(engineID, out ManualStaticOutProduct product, out message))
{
return false;
}
if (!TryBuildManualStaticOutData(product.EngineID, 1, out ManualStaticOutData staticOutData, out message))
{
return false;
}
// 二次校验静置时间,最小分钟数来自 PAD 当前配置,默认 30 分钟。
if (!IsManualStaticTimeEnough(staticOutData, minStaticMinutes, out message))
{
return false;
}
MIS_BASE.Read_PalletCode(opName, out int palletCode);
MisDataFun.OpName_MIS_MOBY_Insert(opName, product.EngineTypeID, product.EngineType, product.EngineID, palletCode, product.OrderForm, 0, 0, "");
// 写入 MES->PLC 产品区PLC 收到 EngineTypeGetOver_MES 后再回传 44 做进站校验。
MIS_BASE.Write_EngineTypeID_MES(opName, product.EngineTypeID);
MIS_BASE.Write_EngineID_MES(opName, product.EngineID);
MIS_BASE.Write_EngineType_MES(opName, product.EngineType);
MIS_BASE.Write_OrderForm_MES(opName, product.OrderForm);
MIS_BASE.Write_EngineTypeGetOver_MES(opName, true);
RememberManualStaticMinutesForProduct(product.EngineID, minStaticMinutes);
message = "PAD确认上线成功" + product.EngineID;
return true;
}
private bool QueryManualStaticOutProduct(string opName, string engineID, decimal minStaticMinutes, out string resultMessage)
{
resultMessage = "";
// 扫码查询只返回产品与静置信息,不写 PLC、不调用进站也不依赖托盘到位/PLC申请上线实时消息。
// PAD 页面可能不是一直打开,托盘到位等实时 MQTT 可能丢失,最终状态由确认上线时后端再次校验。
if (!TryGetManualStaticOutProduct(engineID, out ManualStaticOutProduct product, out resultMessage))
{
return false;
}
if (!TryBuildManualStaticOutData(product.EngineID, 1, out ManualStaticOutData staticOutData, out resultMessage))
{
return false;
}
bool timeEnough = IsManualStaticTimeEnough(staticOutData, minStaticMinutes, out string timeMessage);
MIS_BASE.Read_PartLoad(opName, out bool partLoad);
bool canConfirm = timeEnough && partLoad;
string confirmMessage = canConfirm
? "允许确认上线"
: !timeEnough
? timeMessage
: "PLC尚未申请上线不允许确认上线";
resultMessage = string.Join("^", new string[]
{
product.EngineID,
product.OrderForm,
product.EngineType,
product.EngineTypeID.ToString(),
staticOutData.SourceOpName,
staticOutData.StartTime.ToString("yyyy-MM-dd HH:mm:ss"),
staticOutData.Minutes.ToString("0.##"),
minStaticMinutes.ToString("0.##"),
partLoad ? "1" : "0",
canConfirm ? "1" : "0",
confirmMessage
});
return true;
}
private void SendManualStaticOutResult(string opName, string command, bool success, string message)
{
string value = (success ? "1" : "0") + "^" + message;
SendManualStaticPadMqttMessage(command, opName, value);
// 同步给工位主题保留现有页面状态监听能力PAD 以 OP431PAD 主题为准。
SendMessageFun.SendInfomation(command, value, opName);
if (!success)
{
SendMessage.AsyncSendMessage_Notice(opName, "【" + opName + "】" + message);
}
}
private void SendManualStaticPadMqttMessage(string command, string opName, string value)
{
SendMessage.AsyncSendNotOpMessage(ManualStaticPadTopic, "MES|" + command + "|" + opName + "|" + value);
}
private void RememberManualStaticMinutesForProduct(string engineID, decimal minStaticMinutes)
{
lock (ManualStaticMinutesLocker)
{
ManualStaticMinutesByEngine[engineID] = minStaticMinutes;
}
}
private bool TryGetManualStaticMinutesForProduct(string engineID, out decimal minStaticMinutes)
{
lock (ManualStaticMinutesLocker)
{
if (ManualStaticMinutesByEngine.ContainsKey(engineID))
{
minStaticMinutes = ManualStaticMinutesByEngine[engineID];
return true;
}
}
minStaticMinutes = DefaultManualStaticMinutes;
return false;
}
}
}