From 035f2a81a59532ac9f892dab9ade44304847b4fb Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期一, 06 四月 2026 11:11:36 +0800
Subject: [PATCH] 重构输送线选择器;添加表格展开功能
---
项目资料/设备协议/拘束机对接协议/拘束机对接协议.xlsx | 0
Code/WMS/WIDESEA_WMSClient/src/components/basic/ViewGrid/props.js | 30
.omc/project-memory.json | 63 --
Code/WMS/WIDESEA_WMSClient/src/components/basic/VolTable.vue | 37 +
Code/WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue | 628 ++++++++++++++++++++++-------
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs | 500 +++++++++++++++++------
Code/WMS/WIDESEA_WMSClient/src/components/basic/ViewGrid/ViewGrid.vue | 1
7 files changed, 896 insertions(+), 363 deletions(-)
diff --git a/.omc/project-memory.json b/.omc/project-memory.json
index a09d592..199e998 100644
--- a/.omc/project-memory.json
+++ b/.omc/project-memory.json
@@ -1,6 +1,6 @@
{
"version": "1.0.0",
- "lastScanned": 1774488038530,
+ "lastScanned": 1775442733141,
"projectRoot": "D:\\Git\\ShanMeiXinNengYuan",
"techStack": {
"languages": [],
@@ -36,72 +36,17 @@
"path": "Code",
"purpose": null,
"fileCount": 0,
- "lastAccessed": 1774488038511,
+ "lastAccessed": 1775442733121,
"keyFiles": []
},
"椤圭洰璧勬枡": {
"path": "椤圭洰璧勬枡",
"purpose": null,
"fileCount": 0,
- "lastAccessed": 1774488038512,
+ "lastAccessed": 1775442733121,
"keyFiles": []
}
},
- "hotPaths": [
- {
- "path": "Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_StockService\\StockSerivce.cs",
- "accessCount": 14,
- "lastAccessed": 1774492937086,
- "type": "file"
- },
- {
- "path": "Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_WMSServer\\appsettings.json",
- "accessCount": 5,
- "lastAccessed": 1774490361799,
- "type": "file"
- },
- {
- "path": "Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_WMSServer\\Program.cs",
- "accessCount": 3,
- "lastAccessed": 1774488093580,
- "type": "file"
- },
- {
- "path": "Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_WMSServer\\WIDESEA_WMSServer.csproj",
- "accessCount": 1,
- "lastAccessed": 1774488065335,
- "type": "file"
- },
- {
- "path": "Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_StockService\\StockViewService.cs",
- "accessCount": 1,
- "lastAccessed": 1774492577060,
- "type": "file"
- },
- {
- "path": "Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_StockService\\StockInfoService.cs",
- "accessCount": 1,
- "lastAccessed": 1774492577097,
- "type": "file"
- },
- {
- "path": "Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_StockService\\StockInfoDetailService.cs",
- "accessCount": 1,
- "lastAccessed": 1774492577122,
- "type": "file"
- },
- {
- "path": "Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\BaseServices\\ServiceBase.cs",
- "accessCount": 1,
- "lastAccessed": 1774492577619,
- "type": "file"
- },
- {
- "path": "Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_IStockService\\IStockInfoService.cs",
- "accessCount": 1,
- "lastAccessed": 1774492782997,
- "type": "file"
- }
- ],
+ "hotPaths": [],
"userDirectives": []
}
\ No newline at end of file
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs
index 062265a..c4ecdf4 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs
@@ -20,227 +20,447 @@
public class ConveyorLineTargetAddressSelector
{
/// <summary>
- /// 鎷樻潫鏈哄悕绉板父閲�
+ /// 璁惧灞傜骇锛堜笂灞�/涓嬪眰锛�
/// </summary>
- private const string ConstraintMachineName = "鎷樻潫鏈�";
+ /// <remarks>
+ /// 鐢ㄤ簬鍖哄垎鎷樻潫鏈哄拰鎻掓嫈閽夋満鐨勪笂灞傚伐浣嶅拰涓嬪眰宸ヤ綅銆�
+ /// 鍏ュ簱浠诲姟瀵瑰簲涓婂眰锛圡aterialRequestUpper锛夛紝鍑哄簱浠诲姟瀵瑰簲涓嬪眰锛圡aterialRequestLower锛夈��
+ /// </remarks>
+ private enum Layer
+ {
+ /// <summary>
+ /// 涓婂眰宸ヤ綅
+ /// </summary>
+ Upper,
+
+ /// <summary>
+ /// 涓嬪眰宸ヤ綅
+ /// </summary>
+ Lower
+ }
/// <summary>
- /// 鎻掓嫈閽夋満鍚嶇О甯搁噺
+ /// 鐩爣璁惧绫诲瀷鏋氫妇
/// </summary>
- private const string PinMachineName = "鎻掓嫈閽夋満";
+ /// <remarks>
+ /// 鐢ㄤ簬鏍规嵁鐩爣鍦板潃缂栫爜璇嗗埆闇�瑕佸鎺ョ殑璁惧绫诲瀷銆�
+ /// </remarks>
+ private enum TargetDeviceType
+ {
+ /// <summary>
+ /// 鏃犳湁鏁堣澶囷紙鍦板潃涓嶅湪宸茬煡鑼冨洿鍐咃級
+ /// </summary>
+ None,
+
+ /// <summary>
+ /// 鎷樻潫鏈�
+ /// </summary>
+ /// <remarks>
+ /// 璐熻矗鍥哄畾/绾︽潫鐢垫睜鎵樼洏鐨勮澶囷紝鏈変笂涓嬩袱灞傘��
+ /// </remarks>
+ ConstraintMachine,
+
+ /// <summary>
+ /// 鎻掓嫈閽夋満
+ /// </summary>
+ /// <remarks>
+ /// 璐熻矗鎻掗拡鍜屾嫈閽堟搷浣滅殑璁惧锛屾湁涓婁笅涓ゅ眰銆�
+ /// </remarks>
+ PinMachine
+ }
/// <summary>
- /// 鎷樻潫鏈哄搴旂殑鐐逛綅缂栫爜鍒楄〃
+ /// 鎷樻潫鏈哄搴旂殑鐐逛綅缂栫爜闆嗗悎
/// </summary>
/// <remarks>
/// 褰撶洰鏍囧湴鍧�鍦ㄨ繖浜涚紪鐮佷腑鏃讹紝琛ㄧず闇�瑕佷笌鎷樻潫鏈轰氦浜掋��
+ /// 浣跨敤 HashSet 淇濊瘉 O(1) 鐨� Contains 鏌ユ壘鎬ц兘銆�
/// </remarks>
- private static readonly List<string> ConstraintMachineCodes = new List<string> { "10180", "20090" };
+ private static readonly HashSet<string> ConstraintMachineCodes = new HashSet<string> { "10180", "20090" };
/// <summary>
- /// 鎻掓嫈閽夋満瀵瑰簲鐨勭偣浣嶇紪鐮佸垪琛�
+ /// 鎻掓嫈閽夋満瀵瑰簲鐨勭偣浣嶇紪鐮侀泦鍚�
/// </summary>
/// <remarks>
/// 褰撶洰鏍囧湴鍧�鍦ㄨ繖浜涚紪鐮佷腑鏃讹紝琛ㄧず闇�瑕佷笌鎻掓嫈閽夋満浜や簰銆�
+ /// 浣跨敤 HashSet 淇濊瘉 O(1) 鐨� Contains 鏌ユ壘鎬ц兘銆�
/// </remarks>
- private static readonly List<string> PinMachineCodes = new List<string> { "10190", "20100" };
+ private static readonly HashSet<string> PinMachineCodes = new HashSet<string> { "10190", "20100" };
+
+ /// <summary>
+ /// 鐩爣鍦板潃鍒拌澶囩被鍨嬬殑鏄犲皠
+ /// </summary>
+ /// <remarks>
+ /// 閫氳繃鍗曚竴瀛楀吀瀹炵幇 O(1) 鏌ユ壘锛屾浛浠e師鍏堝垎鍒敤涓や釜 List + Contains + if/else if 鐨勫啓娉曘��
+ /// Key: 鐩爣鍦板潃缂栫爜锛孷alue: 瀵瑰簲鐨勮澶囩被鍨嬨��
+ /// </remarks>
+ private static readonly Dictionary<string, TargetDeviceType> AddressToDeviceType = new Dictionary<string, TargetDeviceType>
+ {
+ // 鎷樻潫鏈虹殑涓や釜鐐逛綅缂栫爜閮芥槧灏勫埌 ConstraintMachine 绫诲瀷
+ { "10180", TargetDeviceType.ConstraintMachine },
+ { "20090", TargetDeviceType.ConstraintMachine },
+ // 鎻掓嫈閽夋満鐨勪袱涓偣浣嶇紪鐮侀兘鏄犲皠鍒� PinMachine 绫诲瀷
+ { "10190", TargetDeviceType.PinMachine },
+ { "20100", TargetDeviceType.PinMachine }
+ };
/// <summary>
/// 鏃ュ織璁板綍鍣�
/// </summary>
+ /// <remarks>
+ /// 閫氳繃 Microsoft.Extensions.Logging 鎺ュ彛娉ㄥ叆锛岀敤浜庣粨鏋勫寲鏃ュ織杈撳嚭銆�
+ /// </remarks>
private readonly ILogger _logger;
/// <summary>
/// 鏋勯�犲嚱鏁�
/// </summary>
- /// <param name="logger">鏃ュ織璁板綍鍣�</param>
+ /// <param name="logger">鏃ュ織璁板綍鍣紝鐢变緷璧栨敞鍏ュ鍣ㄨ嚜鍔ㄦ敞鍏�</param>
public ConveyorLineTargetAddressSelector(ILogger logger)
{
- _logger = logger;
+ _logger = logger; // 淇濆瓨鏃ュ織璁板綍鍣ㄥ疄渚嬶紝渚涘悗缁柟娉曚娇鐢�
}
/// <summary>
/// 澶勭悊鍏ュ簱鍦烘櫙鐨勪笅涓�鍦板潃璇锋眰
/// </summary>
/// <remarks>
- /// 褰撳叆搴撲换鍔℃墽琛屽埌鏌愪釜浣嶇疆鏃惰皟鐢ㄦ鏂规硶銆�
- /// 鍒ゆ柇鐩爣璁惧鏄惁闇�瑕佺墿鏂欐垨鍙互鍑烘枡銆�
+ /// 鍏ュ簱浠诲姟鍒拌揪鏌愪釜浣嶇疆鏃惰皟鐢ㄦ鏂规硶锛屽垽鏂洰鏍囪澶囨槸鍚﹂渶瑕佺墿鏂欍��
+ /// 鍏ュ簱瀵瑰簲涓婂眰宸ヤ綅锛圠ayer.Upper锛夛紝鍥犱负鐗╂枡浠庝笂灞傝繘鍏ヤ粨搴撱��
/// </remarks>
- /// <param name="conveyorLine">杈撻�佺嚎璁惧瀵硅薄</param>
- /// <param name="nextAddress">涓嬩竴鍦板潃/鐩爣璁惧缂栫爜</param>
- /// <param name="childDeviceCode">褰撳墠瀛愯澶囩紪鐮�</param>
+ /// <param name="conveyorLine">杈撻�佺嚎璁惧瀵硅薄锛岀敤浜庡啓鍏ョ洰鏍囧湴鍧�鍜� ACK 淇″彿</param>
+ /// <param name="nextAddress">涓嬩竴鍦板潃/鐩爣璁惧缂栫爜锛岀敤浜庤瘑鍒洰鏍囪澶囩被鍨�</param>
+ /// <param name="childDeviceCode">褰撳墠瀛愯澶囩紪鐮侊紝鐢ㄤ簬绮剧‘瀹氫綅鍐欏叆鍝釜瀛愯澶�</param>
public void HandleInboundNextAddress(CommonConveyorLine conveyorLine, string nextAddress, string childDeviceCode)
{
- _logger.LogDebug("HandleInboundNextAddress锛氬叆搴撲笅涓�鍦板潃锛屽瓙璁惧: {ChildDeviceCode}锛岀洰鏍囧湴鍧�: {NextAddress}", childDeviceCode, nextAddress);
- QuartzLogger.Debug($"HandleInboundNextAddress锛氬叆搴撲笅涓�鍦板潃锛屽瓙璁惧: {childDeviceCode}锛岀洰鏍囧湴鍧�: {nextAddress}", conveyorLine.DeviceCode);
- // 璋冪敤閫氱敤澶勭悊鏂规硶锛宨sUpper = true 琛ㄧず澶勭悊涓婂眰
- HandleDeviceRequest(conveyorLine, nextAddress, childDeviceCode, isUpper: true);
+ // 璁板綍鍏ュ簱鍦烘櫙鐨勮皟璇曟棩蹇楋紝鍖呭惈瀛愯澶囧拰鐩爣鍦板潃淇℃伅
+ WriteDebug(conveyorLine, "鍏ュ簱涓嬩竴鍦板潃", childDeviceCode, nextAddress);
+ // 濮旀墭閫氱敤澶勭悊鏂规硶锛屽叆搴撳搴斾笂灞傦紙isUpper: true锛�
+ HandleDeviceRequest(conveyorLine, nextAddress, childDeviceCode, Layer.Upper);
}
/// <summary>
/// 澶勭悊鍑哄簱鍦烘櫙鐨勪笅涓�鍦板潃璇锋眰
/// </summary>
/// <remarks>
- /// 褰撳嚭搴撲换鍔℃墽琛屽埌鏌愪釜浣嶇疆鏃惰皟鐢ㄦ鏂规硶銆�
- /// 鍒ゆ柇鐩爣璁惧鏄惁闇�瑕佺墿鏂欐垨鍙互鍑烘枡銆�
+ /// 鍑哄簱浠诲姟鍒拌揪鏌愪釜浣嶇疆鏃惰皟鐢ㄦ鏂规硶锛屽垽鏂洰鏍囪澶囨槸鍚﹂渶瑕佸嚭鏂欍��
+ /// 鍑哄簱瀵瑰簲涓嬪眰宸ヤ綅锛圠ayer.Lower锛夛紝鍥犱负鐗╂枡浠庝笅灞傜寮�浠撳簱銆�
/// </remarks>
- /// <param name="conveyorLine">杈撻�佺嚎璁惧瀵硅薄</param>
- /// <param name="nextAddress">涓嬩竴鍦板潃/鐩爣璁惧缂栫爜</param>
- /// <param name="childDeviceCode">褰撳墠瀛愯澶囩紪鐮�</param>
+ /// <param name="conveyorLine">杈撻�佺嚎璁惧瀵硅薄锛岀敤浜庡啓鍏ョ洰鏍囧湴鍧�鍜� ACK 淇″彿</param>
+ /// <param name="nextAddress">涓嬩竴鍦板潃/鐩爣璁惧缂栫爜锛岀敤浜庤瘑鍒洰鏍囪澶囩被鍨�</param>
+ /// <param name="childDeviceCode">褰撳墠瀛愯澶囩紪鐮侊紝鐢ㄤ簬绮剧‘瀹氫綅鍐欏叆鍝釜瀛愯澶�</param>
public void HandleOutboundNextAddress(CommonConveyorLine conveyorLine, string nextAddress, string childDeviceCode)
{
- _logger.LogDebug("HandleOutboundNextAddress锛氬嚭搴撲笅涓�鍦板潃锛屽瓙璁惧: {ChildDeviceCode}锛岀洰鏍囧湴鍧�: {NextAddress}", childDeviceCode, nextAddress);
- QuartzLogger.Debug($"HandleOutboundNextAddress锛氬嚭搴撲笅涓�鍦板潃锛屽瓙璁惧: {childDeviceCode}锛岀洰鏍囧湴鍧�: {nextAddress}", conveyorLine.DeviceCode);
- // 璋冪敤閫氱敤澶勭悊鏂规硶锛宨sUpper = false 琛ㄧず澶勭悊涓嬪眰
- HandleDeviceRequest(conveyorLine, nextAddress, childDeviceCode, isUpper: false);
+ // 璁板綍鍑哄簱鍦烘櫙鐨勮皟璇曟棩蹇楋紝鍖呭惈瀛愯澶囧拰鐩爣鍦板潃淇℃伅
+ WriteDebug(conveyorLine, "鍑哄簱涓嬩竴鍦板潃", childDeviceCode, nextAddress);
+ // 濮旀墭閫氱敤澶勭悊鏂规硶锛屽嚭搴撳搴斾笅灞傦紙isUpper: false锛�
+ HandleDeviceRequest(conveyorLine, nextAddress, childDeviceCode, Layer.Lower);
}
/// <summary>
- /// 閫氱敤璁惧璇锋眰澶勭悊鏂规硶
+ /// 鏍规嵁鐩爣鍦板潃绫诲瀷鍒嗗彂鍒板搴旇澶囧鐞�
/// </summary>
/// <remarks>
- /// 鏍规嵁鐩爣鍦板潃绫诲瀷锛堟嫎鏉熸満/鎻掓嫈閽夋満锛夎皟鐢ㄧ浉搴旂殑澶勭悊閫昏緫銆�
- /// 澶勭悊涓婁笅灞傝澶囩殑鐗╂枡璇锋眰鍜屽嚭鏂欏崗璋冦��
+ /// 閫氳繃 AddressToDeviceType 瀛楀吀灏嗙洰鏍囧湴鍧�鏄犲皠鍒拌澶囩被鍨嬶紝
+ /// 鐒跺悗鍒嗗彂鍒板搴旂殑涓撶敤澶勭悊鏂规硶锛圚andleConstraintMachine / HandlePinMachine锛夈��
+ /// 濡傛灉鐩爣鍦板潃涓嶅湪宸茬煡鏄犲皠琛ㄤ腑锛岀洿鎺ヨ繑鍥烇紝涓嶅仛浠讳綍澶勭悊銆�
/// </remarks>
- /// <param name="conveyorLine">杈撻�佺嚎璁惧瀵硅薄</param>
- /// <param name="nextAddress">涓嬩竴鍦板潃/鐩爣璁惧缂栫爜</param>
- /// <param name="childDeviceCode">褰撳墠瀛愯澶囩紪鐮�</param>
- /// <param name="isUpper">鏄惁澶勭悊涓婂眰锛坱rue=涓婂眰锛宖alse=涓嬪眰锛�</param>
- private void HandleDeviceRequest(CommonConveyorLine conveyorLine, string nextAddress, string childDeviceCode, bool isUpper)
+ /// <param name="conveyorLine">杈撻�佺嚎璁惧瀵硅薄锛屼紶閫掑埌鍏蜂綋璁惧澶勭悊鏂规硶</param>
+ /// <param name="nextAddress">鐩爣璁惧缂栫爜锛岄�氳繃瀛楀吀鏌ユ壘璇嗗埆璁惧绫诲瀷</param>
+ /// <param name="childDeviceCode">瀛愯澶囩紪鐮侊紝浼犻�掑埌鍏蜂綋璁惧澶勭悊鏂规硶</param>
+ /// <param name="layer">璁惧灞傜骇锛堜笂灞傛垨涓嬪眰锛夛紝鍐冲畾璇诲彇鍝粍璇锋眰鏍囧織</param>
+ private void HandleDeviceRequest(CommonConveyorLine conveyorLine, string nextAddress, string childDeviceCode, Layer layer)
{
- // 鑾峰彇鍏ㄥ眬璁惧鍒楄〃
- var devices = Storage.Devices;
-
- // 鍒ゆ柇鐩爣璁惧绫诲瀷
- if (ConstraintMachineCodes.Contains(nextAddress))
+ // 閫氳繃瀛楀吀鏌ユ壘鐩爣鍦板潃瀵瑰簲鐨勮澶囩被鍨嬶紝濡傛灉鎵句笉鍒板垯 deviceType 涓� None
+ if (!AddressToDeviceType.TryGetValue(nextAddress, out var deviceType) || deviceType == TargetDeviceType.None)
{
- // 鎷樻潫鏈哄鐞嗗垎鏀�
- // 鏌ユ壘鎷樻潫鏈鸿澶�
- ConstraintMachine? constraint = devices.OfType<ConstraintMachine>().FirstOrDefault(d => d.DeviceName == ConstraintMachineName);
- if (constraint == null)
- {
- _logger.LogDebug("HandleDeviceRequest锛氭湭鎵惧埌鎷樻潫鏈鸿澶�");
- QuartzLogger.Debug("HandleDeviceRequest锛氭湭鎵惧埌鎷樻潫鏈鸿澶�", conveyorLine.DeviceCode);
- // 鏈壘鍒版嫎鏉熸満璁惧锛岀洿鎺ヨ繑鍥�
- return;
- }
-
- // 澶勭悊鎷樻潫鏈虹殑璇锋眰
- ProcessDeviceRequest(
- conveyorLine,
- childDeviceCode,
- // 鑾峰彇鐗╂枡璇锋眰鏍囧織锛堜笂灞傛垨涓嬪眰锛�
- getMaterialRequest: () => isUpper
- ? constraint.GetValue<ConstraintMachineDBName, short>(ConstraintMachineDBName.MaterialRequestUpper) != 0
- : constraint.GetValue<ConstraintMachineDBName, short>(ConstraintMachineDBName.MaterialRequestLower) != 0,
- // 鑾峰彇鍑烘枡璇锋眰鏍囧織锛堜笂灞傛垨涓嬪眰锛�
- getOutputRequest: () => isUpper
- ? constraint.GetValue<ConstraintMachineDBName, short>(ConstraintMachineDBName.OutputRequestUpper) != 0
- : constraint.GetValue<ConstraintMachineDBName, short>(ConstraintMachineDBName.OutputRequestLower) != 0,
- // 璁剧疆杈撳嚭灏辩华鏍囧織锛堜笂灞傛垨涓嬪眰锛�
- setOutputReady: outputReq =>
- {
- if (isUpper)
- {
- constraint.SetValue(ConstraintMachineDBName.ConstraintTrayOutputReadyUpper, outputReq ? 1 : 0);
- }
- else
- {
- constraint.SetValue(ConstraintMachineDBName.ConstraintTrayOutputReadyLower, outputReq ? 1 : 0);
- }
- },
- "鎷樻潫鏈�");
+ // 鐩爣鍦板潃涓嶅湪宸茬煡鏄犲皠琛ㄤ腑锛岀洿鎺ヨ繑鍥烇紙鍙兘鏄叾浠栫被鍨嬭澶囷級
+ return;
}
- else if (PinMachineCodes.Contains(nextAddress))
+
+ // 鏍规嵁璇嗗埆鍑虹殑璁惧绫诲瀷鍒嗗彂鍒板搴旂殑澶勭悊鏂规硶
+ switch (deviceType)
{
- // 鎻掓嫈閽夋満澶勭悊鍒嗘敮
- // 鏌ユ壘鎻掓嫈閽夋満璁惧
- PinMachine? pinMachine = devices.OfType<PinMachine>().FirstOrDefault(d => d.DeviceName == PinMachineName);
- if (pinMachine == null)
- {
- _logger.LogDebug("HandleDeviceRequest锛氭湭鎵惧埌鎻掓嫈閽夋満璁惧");
- QuartzLogger.Debug("HandleDeviceRequest锛氭湭鎵惧埌鎻掓嫈閽夋満璁惧", conveyorLine.DeviceCode);
- return;
- }
+ case TargetDeviceType.ConstraintMachine:
+ // 鎷樻潫鏈哄鐞嗗垎鏀細鑾峰彇鎷樻潫鏈哄疄渚嬪苟澶勭悊鍏朵笂涓嬪眰璇锋眰
+ HandleConstraintMachine(conveyorLine, childDeviceCode, layer);
+ break; // 澶勭悊瀹屾瘯锛岃烦鍑� switch
- // 澶勭悊鎻掓嫈閽夋満鐨勮姹�
- ProcessDeviceRequest(
- conveyorLine,
- childDeviceCode,
- // 鑾峰彇鐗╂枡璇锋眰鏍囧織锛堜笂灞傛垨涓嬪眰锛�
- getMaterialRequest: () => isUpper
- ? pinMachine.GetValue<PinMachineDBName, short>(PinMachineDBName.MaterialRequestUpper) != 0
- : pinMachine.GetValue<PinMachineDBName, short>(PinMachineDBName.MaterialRequestLower) != 0,
- // 鑾峰彇鍑烘枡璇锋眰鏍囧織锛堜笂灞傛垨涓嬪眰锛�
- getOutputRequest: () => isUpper
- ? pinMachine.GetValue<PinMachineDBName, short>(PinMachineDBName.OutputRequestUpper) != 0
- : pinMachine.GetValue<PinMachineDBName, short>(PinMachineDBName.OutputRequestLower) != 0,
- // 璁剧疆杈撳嚭灏辩华鏍囧織锛堜笂灞傛垨涓嬪眰锛�
- setOutputReady: outputReq =>
- {
- if (isUpper)
- {
- pinMachine.SetValue(PinMachineDBName.PlugPinTrayOutputReadyUpper, outputReq ? 1 : 0);
- }
- else
- {
- pinMachine.SetValue(PinMachineDBName.PlugPinTrayOutputReadyLower, outputReq ? 1 : 0);
- }
- },
- "鎻掓嫈閽夋満");
+ case TargetDeviceType.PinMachine:
+ // 鎻掓嫈閽夋満澶勭悊鍒嗘敮锛氳幏鍙栨彃鎷旈拤鏈哄疄渚嬪苟澶勭悊鍏朵笂涓嬪眰璇锋眰
+ HandlePinMachine(conveyorLine, childDeviceCode, layer);
+ break; // 澶勭悊瀹屾瘯锛岃烦鍑� switch
}
+ }
+
+ /// <summary>
+ /// 澶勭悊鎷樻潫鏈虹殑鐗╂枡/鍑烘枡璇锋眰
+ /// </summary>
+ /// <remarks>
+ /// 鏌ユ壘鎷樻潫鏈鸿澶囷紝鑾峰彇褰撳墠灞傜骇鐨勭墿鏂欒姹傚拰鍑烘枡璇锋眰鐘舵�侊紝
+ /// 鐒跺悗璋冪敤閫氱敤澶勭悊閫昏緫 ProcessDeviceRequest銆�
+ /// </remarks>
+ /// <param name="conveyorLine">杈撻�佺嚎璁惧瀵硅薄锛岀敤浜庨�氱煡鐩爣鍦板潃鍜� ACK</param>
+ /// <param name="childDeviceCode">瀛愯澶囩紪鐮侊紝鐢ㄤ簬绮剧‘瀹氫綅</param>
+ /// <param name="layer">璁惧灞傜骇锛屽喅瀹氳鍙栦笂灞傝繕鏄笅灞傜殑璇锋眰鏍囧織</param>
+ private void HandleConstraintMachine(CommonConveyorLine conveyorLine, string childDeviceCode, Layer layer)
+ {
+ // 浠庡叏灞�璁惧鍒楄〃涓煡鎵惧悕涓�"鎷樻潫鏈�"鐨勬嫎鏉熸満璁惧瀹炰緥
+ var constraint = FindDevice<ConstraintMachine>("鎷樻潫鏈�");
+ if (constraint == null)
+ {
+ // 鏈壘鍒版嫎鏉熸満璁惧锛屽凡鍦� FindDevice 涓褰曟棩蹇楋紝姝ゅ鐩存帴杩斿洖
+ return;
+ }
+
+ // 鑾峰彇褰撳墠灞傜骇锛堜笂灞�/涓嬪眰锛夌殑鐗╂枡璇锋眰鏍囧織锛岄潪闆惰〃绀鸿澶囬渶瑕佺墿鏂�
+ bool materialRequest = GetConstraintFlag(constraint, layer, isMaterial: true);
+ // 鑾峰彇褰撳墠灞傜骇锛堜笂灞�/涓嬪眰锛夌殑鍑烘枡璇锋眰鏍囧織锛岄潪闆惰〃绀鸿澶囨湁璐ц鍑�
+ bool outputRequest = GetConstraintFlag(constraint, layer, isMaterial: false);
+
+ // 鏋勯�犺缃緭鍑哄氨缁爣蹇楃殑濮旀墭锛堟牴鎹眰绾у啓鍏� Upper 鎴� Lower 瀵瑰簲鐨勫瘎瀛樺櫒锛�
+ Action<bool> setOutputReady = outputReady =>
+ SetConstraintOutputReady(constraint, layer, outputReady);
+
+ // 璋冪敤閫氱敤璇锋眰澶勭悊閫昏緫锛屼紶鍏ヨ澶囩被鍨嬫弿杩扮敤浜庢棩蹇楄褰�
+ ProcessDeviceRequest(conveyorLine, childDeviceCode, materialRequest, outputRequest, setOutputReady, "鎷樻潫鏈�");
+ }
+
+ /// <summary>
+ /// 澶勭悊鎻掓嫈閽夋満鐨勭墿鏂�/鍑烘枡璇锋眰
+ /// </summary>
+ /// <remarks>
+ /// 鏌ユ壘鎻掓嫈閽夋満璁惧锛岃幏鍙栧綋鍓嶅眰绾х殑鐗╂枡璇锋眰鍜屽嚭鏂欒姹傜姸鎬侊紝
+ /// 鐒跺悗璋冪敤閫氱敤澶勭悊閫昏緫 ProcessDeviceRequest銆�
+ /// </remarks>
+ /// <param name="conveyorLine">杈撻�佺嚎璁惧瀵硅薄锛岀敤浜庨�氱煡鐩爣鍦板潃鍜� ACK</param>
+ /// <param name="childDeviceCode">瀛愯澶囩紪鐮侊紝鐢ㄤ簬绮剧‘瀹氫綅</param>
+ /// <param name="layer">璁惧灞傜骇锛屽喅瀹氳鍙栦笂灞傝繕鏄笅灞傜殑璇锋眰鏍囧織</param>
+ private void HandlePinMachine(CommonConveyorLine conveyorLine, string childDeviceCode, Layer layer)
+ {
+ // 浠庡叏灞�璁惧鍒楄〃涓煡鎵惧悕涓�"鎻掓嫈閽夋満"鐨勬彃鎷旈拤鏈鸿澶囧疄渚�
+ var pinMachine = FindDevice<PinMachine>("鎻掓嫈閽夋満");
+ if (pinMachine == null)
+ {
+ // 鏈壘鍒版彃鎷旈拤鏈鸿澶囷紝宸插湪 FindDevice 涓褰曟棩蹇楋紝姝ゅ鐩存帴杩斿洖
+ return;
+ }
+
+ // 鑾峰彇褰撳墠灞傜骇锛堜笂灞�/涓嬪眰锛夌殑鐗╂枡璇锋眰鏍囧織锛岄潪闆惰〃绀鸿澶囬渶瑕佺墿鏂�
+ bool materialRequest = GetPinMachineFlag(pinMachine, layer, isMaterial: true);
+ // 鑾峰彇褰撳墠灞傜骇锛堜笂灞�/涓嬪眰锛夌殑鍑烘枡璇锋眰鏍囧織锛岄潪闆惰〃绀鸿澶囨湁璐ц鍑�
+ bool outputRequest = GetPinMachineFlag(pinMachine, layer, isMaterial: false);
+
+ // 鏋勯�犺缃緭鍑哄氨缁爣蹇楃殑濮旀墭锛堟牴鎹眰绾у啓鍏� Upper 鎴� Lower 瀵瑰簲鐨勫瘎瀛樺櫒锛�
+ Action<bool> setOutputReady = outputReady =>
+ SetPinMachineOutputReady(pinMachine, layer, outputReady);
+
+ // 璋冪敤閫氱敤璇锋眰澶勭悊閫昏緫锛屼紶鍏ヨ澶囩被鍨嬫弿杩扮敤浜庢棩蹇楄褰�
+ ProcessDeviceRequest(conveyorLine, childDeviceCode, materialRequest, outputRequest, setOutputReady, "鎻掓嫈閽夋満");
+ }
+
+ /// <summary>
+ /// 鏌ユ壘鎸囧畾鍚嶇О鐨勮澶�
+ /// </summary>
+ /// <remarks>
+ /// 浠庡叏灞�璁惧鍒楄〃 Storage.Devices 涓�氳繃璁惧绫诲瀷鍜屽悕绉版煡鎵捐澶囧疄渚嬨��
+ /// 杩欐槸涓�涓硾鍨嬫柟娉曪紝鍙互閫傜敤浜� ConstraintMachine銆丳inMachine 绛夊绉嶈澶囩被鍨嬨��
+ /// </remarks>
+ /// <typeparam name="T">璁惧绫诲瀷锛屽繀椤绘槸寮曠敤绫诲瀷锛堝 ConstraintMachine銆丳inMachine锛�</typeparam>
+ /// <param name="deviceName">璁惧鍚嶇О锛岀敤浜庣簿纭尮閰嶈澶囩殑 DeviceName 灞炴��</param>
+ /// <returns>鎵惧埌鐨勮澶囧疄渚嬶紝鏈壘鍒板垯杩斿洖 null</returns>
+ private T? FindDevice<T>(string deviceName) where T : class
+ {
+ // OfType<T>() 绛涢�夊嚭鎸囧畾绫诲瀷鐨勮澶囷紝FirstOrDefault 鎸夊悕绉扮簿纭尮閰�
+ var device = Storage.Devices.OfType<T>().FirstOrDefault(d => GetDeviceName(d) == deviceName);
+ if (device == null)
+ {
+ // 璁惧鏈壘鍒版椂璁板綍璋冭瘯鏃ュ織锛屾柟渚挎帓鏌ラ厤缃棶棰�
+ _logger.LogDebug("FindDevice锛氭湭鎵惧埌 {DeviceName}", deviceName);
+ }
+ return device; // 鍙兘涓� null锛岀敱璋冪敤鏂硅礋璐� null 妫�鏌�
+ }
+
+ /// <summary>
+ /// 閫氳繃澶氭�佽幏鍙栦换鎰忚澶囩殑鍚嶇О
+ /// </summary>
+ /// <remarks>
+ /// 浣跨敤 switch 琛ㄨ揪寮忔牴鎹澶囩殑鍏蜂綋绫诲瀷鑾峰彇鍏� DeviceName 灞炴�э紝
+ /// 閬垮厤涓烘瘡绉嶈澶囩被鍨嬬紪鍐欑嫭绔嬬殑鍙嶅皠鎴栧睘鎬ц闂唬鐮併��
+ /// 褰撳墠鏀寔 ConstraintMachine 鍜� PinMachine 涓ょ绫诲瀷銆�
+ /// </remarks>
+ /// <typeparam name="T">璁惧绫诲瀷</typeparam>
+ /// <param name="device">璁惧瀹炰緥锛岄潪绌�</param>
+ /// <returns>璁惧鐨勫悕绉板瓧绗︿覆锛屽鏋滅被鍨嬩笉鍖归厤鍒欒繑鍥炵┖瀛楃涓�</returns>
+ private static string GetDeviceName<T>(T device) where T : class
+ {
+ // 妯″紡鍖归厤锛氭牴鎹澶囩殑鍏蜂綋杩愯鏃剁被鍨嬭繑鍥炲搴旂殑 DeviceName
+ return device switch
+ {
+ ConstraintMachine cm => cm.DeviceName, // 鎷樻潫鏈鸿繑鍥炲叾璁惧鍚嶇О
+ PinMachine pm => pm.DeviceName, // 鎻掓嫈閽夋満杩斿洖鍏惰澶囧悕绉�
+ _ => string.Empty // 鏈煡绫诲瀷杩斿洖绌哄瓧绗︿覆锛堢悊璁轰笂涓嶄細璧板埌杩欓噷锛�
+ };
+ }
+
+ /// <summary>
+ /// 鑾峰彇鎷樻潫鏈虹殑璇锋眰鏍囧織锛堢墿鏂欒姹傛垨鍑烘枡璇锋眰锛�
+ /// </summary>
+ /// <remarks>
+ /// 鏍规嵁 isMaterial 鍙傛暟鍐冲畾璇诲彇鐗╂枡璇锋眰杩樻槸鍑烘枡璇锋眰瀵勫瓨鍣紝
+ /// 鍐嶆牴鎹� layer 鍙傛暟鍐冲畾璇诲彇涓婂眰锛圲pper锛夎繕鏄笅灞傦紙Lower锛夊瘎瀛樺櫒銆�
+ /// 杩斿洖鍊艰〃绀鸿姹傛槸鍚︽湁鏁堬紙闈為浂涓烘湁鏁堬級銆�
+ /// </remarks>
+ /// <param name="constraint">鎷樻潫鏈鸿澶囧疄渚嬶紝鐢ㄤ簬璇诲彇 PLC 瀵勫瓨鍣ㄥ��</param>
+ /// <param name="layer">璁惧灞傜骇锛屽喅瀹氳鍙� Upper 杩樻槸 Lower 瀵勫瓨鍣�</param>
+ /// <param name="isMaterial">true=璇诲彇鐗╂枡璇锋眰鏍囧織锛宖alse=璇诲彇鍑烘枡璇锋眰鏍囧織</param>
+ /// <returns>璇锋眰鏍囧織鏄惁鏈夋晥锛坱rue=鏈夎姹傦紝false=鏃犺姹傦級</returns>
+ private bool GetConstraintFlag(ConstraintMachine constraint, Layer layer, bool isMaterial)
+ {
+ // 鏍规嵁 isMaterial 閫夋嫨瀵瑰簲鐨勫瘎瀛樺櫒鍚嶇О瀵癸紙鐗╂枡璇锋眰鎴栧嚭鏂欒姹傦級
+ var (materialKey, outputKey) = isMaterial
+ ? (ConstraintMachineDBName.MaterialRequestUpper, ConstraintMachineDBName.MaterialRequestLower) // 鐗╂枡璇锋眰
+ : (ConstraintMachineDBName.OutputRequestUpper, ConstraintMachineDBName.OutputRequestLower); // 鍑烘枡璇锋眰
+
+ // 鏍规嵁 layer 閫夋嫨鍏蜂綋浣跨敤 Upper 杩樻槸 Lower 鐗堟湰鐨勫瘎瀛樺櫒
+ var key = layer == Layer.Upper ? materialKey : outputKey;
+ // 璇诲彇瀵勫瓨鍣ㄥ�硷紝闈為浂琛ㄧず鏈夎姹傦紝杩斿洖甯冨皵鍊�
+ return constraint.GetValue<ConstraintMachineDBName, short>(key) != 0;
+ }
+
+ /// <summary>
+ /// 鑾峰彇鎻掓嫈閽夋満鐨勮姹傛爣蹇楋紙鐗╂枡璇锋眰鎴栧嚭鏂欒姹傦級
+ /// </summary>
+ /// <remarks>
+ /// 涓� GetConstraintFlag 閫昏緫鐩稿悓锛屼絾鎿嶄綔瀵硅薄鏄彃鎷旈拤鏈猴紙PinMachine锛夈��
+ /// 鏍规嵁 isMaterial 鍙傛暟鍐冲畾璇诲彇鐗╂枡璇锋眰杩樻槸鍑烘枡璇锋眰瀵勫瓨鍣紝
+ /// 鍐嶆牴鎹� layer 鍙傛暟鍐冲畾璇诲彇涓婂眰锛圲pper锛夎繕鏄笅灞傦紙Lower锛夊瘎瀛樺櫒銆�
+ /// </remarks>
+ /// <param name="pinMachine">鎻掓嫈閽夋満璁惧瀹炰緥锛岀敤浜庤鍙� PLC 瀵勫瓨鍣ㄥ��</param>
+ /// <param name="layer">璁惧灞傜骇锛屽喅瀹氳鍙� Upper 杩樻槸 Lower 瀵勫瓨鍣�</param>
+ /// <param name="isMaterial">true=璇诲彇鐗╂枡璇锋眰鏍囧織锛宖alse=璇诲彇鍑烘枡璇锋眰鏍囧織</param>
+ /// <returns>璇锋眰鏍囧織鏄惁鏈夋晥锛坱rue=鏈夎姹傦紝false=鏃犺姹傦級</returns>
+ private bool GetPinMachineFlag(PinMachine pinMachine, Layer layer, bool isMaterial)
+ {
+ // 鏍规嵁 isMaterial 閫夋嫨瀵瑰簲鐨勫瘎瀛樺櫒鍚嶇О瀵癸紙鐗╂枡璇锋眰鎴栧嚭鏂欒姹傦級
+ var (materialKey, outputKey) = isMaterial
+ ? (PinMachineDBName.MaterialRequestUpper, PinMachineDBName.MaterialRequestLower) // 鐗╂枡璇锋眰
+ : (PinMachineDBName.OutputRequestUpper, PinMachineDBName.OutputRequestLower); // 鍑烘枡璇锋眰
+
+ // 鏍规嵁 layer 閫夋嫨鍏蜂綋浣跨敤 Upper 杩樻槸 Lower 鐗堟湰鐨勫瘎瀛樺櫒
+ var key = layer == Layer.Upper ? materialKey : outputKey;
+ // 璇诲彇瀵勫瓨鍣ㄥ�硷紝闈為浂琛ㄧず鏈夎姹傦紝杩斿洖甯冨皵鍊�
+ return pinMachine.GetValue<PinMachineDBName, short>(key) != 0;
+ }
+
+ /// <summary>
+ /// 璁剧疆鎷樻潫鏈虹殑杈撳嚭灏辩华鏍囧織
+ /// </summary>
+ /// <remarks>
+ /// 鍚戞嫎鏉熸満鐨� PLC 瀵勫瓨鍣ㄥ啓鍏ヨ緭鍑哄氨缁姸鎬侊紝鍛婄煡鎷樻潫鏈哄彲浠ョ户缁嚭鏂欍��
+ /// 鏍规嵁 layer 鍙傛暟鍐冲畾鍐欏叆涓婂眰锛圕onstraintTrayOutputReadyUpper锛夎繕鏄笅灞傦紙ConstraintTrayOutputReadyLower锛夊瘎瀛樺櫒銆�
+ /// </remarks>
+ /// <param name="constraint">鎷樻潫鏈鸿澶囧疄渚嬶紝鐢ㄤ簬鍐欏叆 PLC 瀵勫瓨鍣�</param>
+ /// <param name="layer">璁惧灞傜骇锛屽喅瀹氬啓鍏� Upper 杩樻槸 Lower 瀵勫瓨鍣�</param>
+ /// <param name="outputReady">杈撳嚭灏辩华鐘舵�侊紝true=鍙互鍑烘枡锛宖alse=涓嶈兘鍑烘枡</param>
+ private void SetConstraintOutputReady(ConstraintMachine constraint, Layer layer, bool outputReady)
+ {
+ // 鏍规嵁 layer 閫夋嫨瀵瑰簲鐨勮緭鍑哄氨缁瘎瀛樺櫒锛圲pper 鎴� Lower锛�
+ var key = layer == Layer.Upper
+ ? ConstraintMachineDBName.ConstraintTrayOutputReadyUpper // 涓婂眰杈撳嚭灏辩华瀵勫瓨鍣�
+ : ConstraintMachineDBName.ConstraintTrayOutputReadyLower; // 涓嬪眰杈撳嚭灏辩华瀵勫瓨鍣�
+ // 鍚� PLC 鍐欏叆鍊硷紝outputReady 涓� true 鏃跺啓鍏� 1锛屽惁鍒欏啓鍏� 0
+ constraint.SetValue(key, outputReady ? true : false);
+ }
+
+ /// <summary>
+ /// 璁剧疆鎻掓嫈閽夋満鐨勮緭鍑哄氨缁爣蹇�
+ /// </summary>
+ /// <remarks>
+ /// 鍚戞彃鎷旈拤鏈虹殑 PLC 瀵勫瓨鍣ㄥ啓鍏ヨ緭鍑哄氨缁姸鎬侊紝鍛婄煡鎻掓嫈閽夋満鍙互缁х画鍑烘枡銆�
+ /// 鏍规嵁 layer 鍙傛暟鍐冲畾鍐欏叆涓婂眰锛圥lugPinTrayOutputReadyUpper锛夎繕鏄笅灞傦紙PlugPinTrayOutputReadyLower锛夊瘎瀛樺櫒銆�
+ /// </remarks>
+ /// <param name="pinMachine">鎻掓嫈閽夋満璁惧瀹炰緥锛岀敤浜庡啓鍏� PLC 瀵勫瓨鍣�</param>
+ /// <param name="layer">璁惧灞傜骇锛屽喅瀹氬啓鍏� Upper 杩樻槸 Lower 瀵勫瓨鍣�</param>
+ /// <param name="outputReady">杈撳嚭灏辩华鐘舵�侊紝true=鍙互鍑烘枡锛宖alse=涓嶈兘鍑烘枡</param>
+ private void SetPinMachineOutputReady(PinMachine pinMachine, Layer layer, bool outputReady)
+ {
+ // 鏍规嵁 layer 閫夋嫨瀵瑰簲鐨勮緭鍑哄氨缁瘎瀛樺櫒锛圲pper 鎴� Lower锛�
+ var key = layer == Layer.Upper
+ ? PinMachineDBName.PlugPinTrayOutputReadyUpper // 涓婂眰杈撳嚭灏辩华瀵勫瓨鍣�
+ : PinMachineDBName.PlugPinTrayOutputReadyLower; // 涓嬪眰杈撳嚭灏辩华瀵勫瓨鍣�
+ // 鍚� PLC 鍐欏叆鍊硷紝outputReady 涓� true 鏃跺啓鍏� 1锛屽惁鍒欏啓鍏� 0
+ pinMachine.SetValue(key, outputReady ? true : false);
}
/// <summary>
/// 澶勭悊璁惧璇锋眰鐨勬牳蹇冮�昏緫
/// </summary>
/// <remarks>
- /// 鏍规嵁鐗╂枡璇锋眰鍜屽嚭鏂欒姹傜殑鐘舵�侊細
- /// - 濡傛灉鏈夌墿鏂欒姹傦紝璁剧疆鐩爣鍦板潃骞跺彂閫� ACK
- /// - 濡傛灉鏈夊嚭鏂欒姹傦紝璁剧疆璁惧鐨勮緭鍑哄氨缁爣蹇�
+ /// 鏍规嵁鐗╂枡璇锋眰鍜屽嚭鏂欒姹傜殑鐘舵�佸喅瀹氳涓猴細
+ /// - 濡傛灉璁惧闇�瑕佺墿鏂欙紙materialRequest=true锛夛紝璁剧疆杈撻�佺嚎鐨勭洰鏍囧湴鍧�涓� 1锛堟湁鏂欒繘鏉ワ級骞跺洖澶� ACK 纭淇″彿
+ /// - 濡傛灉璁惧涓嶉渶瑕佺墿鏂欙紙materialRequest=false锛夛紝鍒欓�氱煡璁惧鍙互缁х画鍑烘枡锛坰etOutputReady锛�
+ ///
+ /// 杩欐槸鎷樻潫鏈哄拰鎻掓嫈閽夋満鍏辩敤鐨勫鐞嗛�昏緫锛岃澶囩壒鏈夌殑閮ㄥ垎宸插湪姝ゆ柟娉曞灏佽銆�
/// </remarks>
- /// <param name="conveyorLine">杈撻�佺嚎璁惧瀵硅薄</param>
- /// <param name="childDeviceCode">褰撳墠瀛愯澶囩紪鐮�</param>
- /// <param name="getMaterialRequest">鑾峰彇鐗╂枡璇锋眰鐘舵�佺殑濮旀墭</param>
- /// <param name="getOutputRequest">鑾峰彇鍑烘枡璇锋眰鐘舵�佺殑濮旀墭</param>
- /// <param name="setOutputReady">璁剧疆杈撳嚭灏辩华鏍囧織鐨勫鎵�</param>
- /// <param name="deviceType">璁惧绫诲瀷鎻忚堪</param>
+ /// <param name="conveyorLine">杈撻�佺嚎璁惧瀵硅薄锛岀敤浜庡啓鍏ョ洰鏍囧湴鍧�锛圱arget锛夊拰 ACK 淇″彿</param>
+ /// <param name="childDeviceCode">瀛愯澶囩紪鐮侊紝鐢ㄤ簬绮剧‘瀹氫綅鍐欏叆鍝釜瀛愯澶�</param>
+ /// <param name="materialRequest">鐗╂枡璇锋眰鏍囧織锛宼rue=璁惧褰撳墠闇�瑕佽ˉ鍏呯墿鏂�</param>
+ /// <param name="outputRequest">鍑烘枡璇锋眰鏍囧織锛宼rue=璁惧褰撳墠鏈夌墿鏂欓渶瑕佽緭鍑猴紙閰嶅悎 materialRequest=false 鏃朵娇鐢級</param>
+ /// <param name="setOutputReady">璁剧疆璁惧杈撳嚭灏辩华鏍囧織鐨勫鎵橈紝鏍规嵁灞傜骇鍐欏叆 Upper 鎴� Lower 瀵勫瓨鍣�</param>
+ /// <param name="deviceType">璁惧绫诲瀷鎻忚堪瀛楃涓诧紝鐢ㄤ簬鏃ュ織杈撳嚭</param>
private void ProcessDeviceRequest(
CommonConveyorLine conveyorLine,
string childDeviceCode,
- Func<bool> getMaterialRequest,
- Func<bool> getOutputRequest,
+ bool materialRequest,
+ bool outputRequest,
Action<bool> setOutputReady,
string deviceType)
{
- // 鑾峰彇鐗╂枡璇锋眰鐘舵��
- bool materialReq = getMaterialRequest();
-
- // 鑾峰彇鍑烘枡璇锋眰鐘舵��
- bool outputReq = getOutputRequest();
-
+ // 璁板綍褰撳墠璇锋眰鐘舵�佺殑璋冭瘯鏃ュ織锛屼緵鎺掓煡闂浣跨敤
_logger.LogDebug("ProcessDeviceRequest锛歿DeviceType}锛屽瓙璁惧: {ChildDeviceCode}锛岀墿鏂欒姹�: {MaterialReq}锛屽嚭鏂欒姹�: {OutputReq}",
- deviceType, childDeviceCode, materialReq, outputReq);
- QuartzLogger.Debug($"ProcessDeviceRequest锛歿deviceType}锛屽瓙璁惧: {childDeviceCode}锛岀墿鏂欒姹�: {materialReq}锛屽嚭鏂欒姹�: {outputReq}", conveyorLine.DeviceCode);
+ deviceType, childDeviceCode, materialRequest, outputRequest);
+ // 鍚屾鍐欏叆 Quartz 鏃ュ織鏂囦欢锛堝弻鍐欏彲杩芥函锛岃繖閲屼繚鐣欎笌鍘熼�昏緫涓�鑷寸殑琛屼负锛�
+ QuartzLogger.Debug($"ProcessDeviceRequest锛歿deviceType}锛屽瓙璁惧: {childDeviceCode}锛岀墿鏂欒姹�: {materialRequest}锛屽嚭鏂欒姹�: {outputRequest}", conveyorLine.DeviceCode);
- // 濡傛灉璁惧闇�瑕佺墿鏂�
- if (materialReq)
+ // 鍒嗘敮鍒ゆ柇锛氳澶囨槸闇�瑕佺墿鏂欒繕鏄渶瑕佸嚭鏂�
+ if (materialRequest)
{
- // 璁剧疆鐩爣鍦板潃涓� 1锛堣〃绀烘湁鏂欒繘鏉ワ級
+ // 璁惧闇�瑕佺墿鏂� -> 閫氱煡杈撻�佺嚎鏈夋枡杩囨潵
+ // 1. 璁剧疆鐩爣鍦板潃涓� 1锛岃〃绀�"鏈夋枡杩涘叆"
conveyorLine.SetValue(ConveyorLineDBNameNew.Target, 1, childDeviceCode);
-
- // 鍥炲 ACK 纭淇″彿
+ // 2. 鍥炲 ACK 纭淇″彿锛屽憡鐭ヨ澶囧凡鏀跺埌璇锋眰
conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, 1, childDeviceCode);
-
+ // 3. 璁板綍淇℃伅鏃ュ織锛岃〃鏄庡凡瀹屾垚鐩爣鍦板潃璁剧疆鍜� ACK 鍥炲
_logger.LogInformation("ProcessDeviceRequest锛歿DeviceType} 闇�瑕佺墿鏂欙紝宸茶缃洰鏍囧湴鍧�鍜孉CK", deviceType);
QuartzLogger.Info($"ProcessDeviceRequest锛歿deviceType} 闇�瑕佺墿鏂欙紝宸茶缃洰鏍囧湴鍧�鍜孉CK", conveyorLine.DeviceCode);
}
else
{
- // 璁惧涓嶉渶瑕佺墿鏂欙紝璁剧疆杈撳嚭灏辩华鏍囧織
- // 閫氱煡璁惧鍙互缁х画鍑烘枡
- setOutputReady(outputReq);
+ // 璁惧涓嶉渶瑕佺墿鏂� -> 閫氱煡璁惧鍙互缁х画鍑烘枡锛堟棤璁哄綋鍓嶆槸鍚︽湁璐ц鍑猴紝閮借閫氱煡锛�
+ // outputRequest 琛ㄧず璁惧褰撳墠鏄惁纭疄鏈夎揣锛屽鏋滄病鏈夎揣鍒� outputReady=false锛岃澶囨敹鍒板悗绛夊緟
+ setOutputReady(outputRequest);
}
}
+
+ /// <summary>
+ /// 鍐欏叆璋冭瘯鏃ュ織锛堝悓鏃惰緭鍑哄埌涓や釜鏃ュ織绯荤粺锛�
+ /// </summary>
+ /// <remarks>
+ /// 缁熶竴鍏ュ彛鐐规棩蹇楁牸寮忥紝鍚屾椂鍚� Microsoft.Extensions.Logging 鍜� QuartzLogger 鍐欏叆锛�
+ /// 淇濊瘉鏃ュ織鏃㈣兘鍦ㄦ帶鍒跺彴鏌ョ湅涔熻兘鍦ㄦ枃浠朵腑杩芥函銆�
+ /// </remarks>
+ /// <param name="conveyorLine">杈撻�佺嚎璁惧瀵硅薄锛岀敤浜庤幏鍙栬澶囩紪鐮佸啓鍏� QuartzLogger</param>
+ /// <param name="scenario">鍦烘櫙鎻忚堪锛屽"鍏ュ簱涓嬩竴鍦板潃"鎴�"鍑哄簱涓嬩竴鍦板潃"</param>
+ /// <param name="childDeviceCode">瀛愯澶囩紪鐮�</param>
+ /// <param name="nextAddress">鐩爣璁惧缂栫爜</param>
+ private void WriteDebug(CommonConveyorLine conveyorLine, string scenario, string childDeviceCode, string nextAddress)
+ {
+ // 鍐欏叆缁撴瀯鍖栨棩蹇楋紙鍙 Serilog 绛夋棩蹇楁鏋舵崟鑾凤級
+ _logger.LogDebug("Handle{Scenario}锛氬瓙璁惧: {ChildDeviceCode}锛岀洰鏍囧湴鍧�: {NextAddress}",
+ scenario, childDeviceCode, nextAddress);
+ // 鍐欏叆 Quartz 涓撶敤鏃ュ織鏂囦欢锛堜緵瀹氭椂浠诲姟杞ㄨ抗杩借釜锛�
+ QuartzLogger.Debug($"Handle{scenario}锛氬瓙璁惧: {childDeviceCode}锛岀洰鏍囧湴鍧�: {nextAddress}", conveyorLine.DeviceCode);
+ }
}
}
diff --git a/Code/WMS/WIDESEA_WMSClient/src/components/basic/ViewGrid/ViewGrid.vue b/Code/WMS/WIDESEA_WMSClient/src/components/basic/ViewGrid/ViewGrid.vue
index dfc84c2..02a7a75 100644
--- a/Code/WMS/WIDESEA_WMSClient/src/components/basic/ViewGrid/ViewGrid.vue
+++ b/Code/WMS/WIDESEA_WMSClient/src/components/basic/ViewGrid/ViewGrid.vue
@@ -456,6 +456,7 @@
<vol-table
ref="table"
:single="single"
+ :expand="tableExpand"
:rowKey="rowKey"
:loadTreeChildren="loadTreeTableChildren"
@loadBefore="loadTableBefore"
diff --git a/Code/WMS/WIDESEA_WMSClient/src/components/basic/ViewGrid/props.js b/Code/WMS/WIDESEA_WMSClient/src/components/basic/ViewGrid/props.js
index 5d0ebc6..138680b 100644
--- a/Code/WMS/WIDESEA_WMSClient/src/components/basic/ViewGrid/props.js
+++ b/Code/WMS/WIDESEA_WMSClient/src/components/basic/ViewGrid/props.js
@@ -1,55 +1,61 @@
let props = {
- columns: {//褰撳墠琛ㄧ殑閰嶇疆淇℃伅
+ columns: {
type: Array,
default: () => {
return [];
}
},
- detail: {//浠庤〃鏄庣粏閰嶇疆
+ detail: {
type: Object,
default: () => {
return {
- columns: [],//浠庤〃鍒�
- sortName: ""//浠庤〃鎺掑簭瀛楁
+ columns: [],
+ sortName: ""
};
}
},
- editFormFields: {//鏂板缓銆佺紪杈戝瓧娈�(key/value)
+ editFormFields: {
type: Object,
default: () => {
return {};
}
},
- editFormOptions: {//鏂板缓銆佺紪杈戦厤缃俊鎭�
+ editFormOptions: {
type: Array,
default: () => {
return [];
}
},
- searchFormFields: {//鏌ヨ瀛楁(key/value)
+ searchFormFields: {
type: Object,
default: () => {
return {};
}
},
- searchFormOptions: {//鏌ヨ閰嶇疆淇℃伅(key/value)
+ searchFormOptions: {
type: Array,
default: () => {
return [];
}
},
- table: {//琛ㄧ殑閰嶇疆淇℃伅锛氫富閿�佹帓搴忕瓑
+ table: {
type: Object,
default: () => {
return {};
}
},
- extend: {//琛ㄧ殑鎵╁睍鏂规硶涓庣粍浠堕兘鍚堝苟鍒版灞炴�т腑
+ tableExpand: {
+ type: Object,
+ default: () => {
+ return {};
+ }
+ },
+ extend: {
type: Object,
default: () => {
return {};
}
}
-}
+};
-export default props;
\ No newline at end of file
+export default props;
diff --git a/Code/WMS/WIDESEA_WMSClient/src/components/basic/VolTable.vue b/Code/WMS/WIDESEA_WMSClient/src/components/basic/VolTable.vue
index 6ca1e90..7d4f846 100644
--- a/Code/WMS/WIDESEA_WMSClient/src/components/basic/VolTable.vue
+++ b/Code/WMS/WIDESEA_WMSClient/src/components/basic/VolTable.vue
@@ -21,6 +21,7 @@
@select="userSelect"
@select-all="userSelect"
@selection-change="selectionChange"
+ @expand-change="expandChange"
@row-dblclick="rowDbClick"
@row-click="rowClick"
@header-click="headerClick"
@@ -38,6 +39,24 @@
style="width: 100%"
:scrollbar-always-on="true"
>
+ <el-table-column
+ v-if="showExpand"
+ type="expand"
+ :fixed="expand.fixed"
+ :width="expand.width || 55"
+ >
+ <template #default="scope">
+ <div class="expand-cell">
+ <table-render
+ v-if="expand.render && typeof expand.render == 'function'"
+ :row="scope.row"
+ :index="scope.$index"
+ :column="expand"
+ :render="expand.render"
+ ></table-render>
+ </div>
+ </template>
+ </el-table-column>
<el-table-column
v-if="ck"
type="selection"
@@ -559,6 +578,12 @@
return 1;
},
},
+ expand: {
+ type: Object,
+ default: () => {
+ return {};
+ },
+ },
pagination: {
type: Object,
default: function () {
@@ -834,6 +859,9 @@
this.defaultLoadPage && this.load();
},
computed: {
+ showExpand() {
+ return !!(this.expand && typeof this.expand.render === "function");
+ },
filterColumns() {
return this.columns.filter((x, index) => {
if (!x.field) {
@@ -844,6 +872,12 @@
},
},
methods: {
+ expandChange(row, expandedRows) {
+ if (this.expand && typeof this.expand.onChange === "function") {
+ this.expand.onChange(row, expandedRows, this);
+ }
+ this.$emit("expandChange", { row, expandedRows });
+ },
watchRowSelectChange(newLen, oldLen) {
if (newLen < oldLen && this.selectRows.length) {
this.selectRows = [];
@@ -1784,6 +1818,9 @@
border-bottom: 1px solid;
padding-bottom: 2px;
}
+.vol-table .expand-cell {
+ padding: 8px 0;
+}
.vol-table .empty-tag {
border: none;
background: none;
diff --git a/Code/WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue b/Code/WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue
index f7ec3e1..96fae1f 100644
--- a/Code/WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue
+++ b/Code/WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue
@@ -1,154 +1,478 @@
-
<template>
- <view-grid
- ref="grid"
- :columns="columns"
- :detail="detail"
- :editFormFields="editFormFields"
- :editFormOptions="editFormOptions"
- :searchFormFields="searchFormFields"
- :searchFormOptions="searchFormOptions"
- :table="table"
- :extend="extend"
- >
- </view-grid>
- </template>
- <script>
- import extend from "@/extension/stock/stockInfo.js";
- import { ref, defineComponent } from "vue";
- export default defineComponent({
- setup() {
- const table = ref({
- key: "id",
- footer: "Foots",
- cnName: "搴撳瓨淇℃伅",
- name: "stockInfo",
- url: "/StockInfo/",
- sortName: "id",
- });
- const editFormFields = ref({
- deviceCode: "",
- deviceName: "",
- deviceType: "",
- deviceStatus: "",
- deviceIp: "",
- devicePort: "",
- devicePlcType: "",
- deviceRemark: "",
- });
- const editFormOptions = ref([
- [
- {field:'palletCode',title:'鎵樼洏缂栧彿',type:'string'},
- {field:'locationCode',title:'璐т綅缂栧彿',type:'string'},
- ]
+ <view-grid
+ ref="grid"
+ :columns="columns"
+ :detail="detail"
+ :editFormFields="editFormFields"
+ :editFormOptions="editFormOptions"
+ :searchFormFields="searchFormFields"
+ :searchFormOptions="searchFormOptions"
+ :table="table"
+ :tableExpand="tableExpand"
+ :extend="extend"
+ >
+ </view-grid>
+</template>
+
+<script>
+import extend from "@/extension/stock/stockInfo.js";
+import {
+ defineComponent,
+ getCurrentInstance,
+ h,
+ reactive,
+ ref,
+ resolveComponent,
+} from "vue";
+
+const TEXT = {
+ pageName: "搴撳瓨淇℃伅",
+ palletCode: "鎵樼洏缂栧彿",
+ locationCode: "璐т綅缂栧彿",
+ warehouse: "浠撳簱",
+ creator: "鍒涘缓浜�",
+ createDate: "鍒涘缓鏃堕棿",
+ modifier: "淇敼浜�",
+ modifyDate: "淇敼鏃堕棿",
+ detailName: "搴撳瓨鏄庣粏",
+ materielName: "鐗╂枡鍚嶇О",
+ serialNumber: "鐢佃姱鐮�",
+ stockQuantity: "搴撳瓨鏁伴噺",
+ status: "鐘舵��",
+ inboundOrderRowNo: "閫氶亾鍙�",
+ detailLoading: "搴撳瓨鏄庣粏鍔犺浇涓�...",
+ detailLoadFailed: "搴撳瓨鏄庣粏鍔犺浇澶辫触",
+ detailEmpty: "褰撳墠搴撳瓨澶存殏鏃犳槑缁嗘暟鎹�",
+ expandPrefix: "鎵樼洏锛�",
+ expandMiddle: " / ",
+ expandLocation: "璐т綅锛�",
+};
+
+export default defineComponent({
+ setup() {
+ const { proxy } = getCurrentInstance();
+ const ElTable = resolveComponent("el-table");
+ const ElTableColumn = resolveComponent("el-table-column");
+
+ const table = ref({
+ key: "id",
+ footer: "Foots",
+ cnName: TEXT.pageName,
+ name: "stockInfo",
+ url: "/StockInfo/",
+ sortName: "id",
+ });
+
+ const editFormFields = ref({
+ palletCode: "",
+ locationCode: "",
+ });
+
+ const editFormOptions = ref([
+ [
+ { field: "palletCode", title: TEXT.palletCode, type: "string" },
+ { field: "locationCode", title: TEXT.locationCode, type: "string" },
+ ],
+ ]);
+
+ const searchFormFields = ref({
+ palletCode: "",
+ locationCode: "",
+ });
+
+ const searchFormOptions = ref([
+ [
+ { title: TEXT.palletCode, field: "palletCode", type: "like" },
+ { title: TEXT.locationCode, field: "locationCode", type: "like" },
+ ],
+ ]);
+
+ const columns = ref([
+ {
+ field: "id",
+ title: "Id",
+ type: "int",
+ width: 90,
+ hidden: true,
+ readonly: true,
+ require: true,
+ align: "left",
+ },
+ {
+ field: "palletCode",
+ title: TEXT.palletCode,
+ type: "string",
+ width: 120,
+ align: "left",
+ },
+ {
+ field: "locationCode",
+ title: TEXT.locationCode,
+ type: "string",
+ width: 150,
+ align: "left",
+ },
+ {
+ field: "warehouseId",
+ title: TEXT.warehouse,
+ type: "select",
+ width: 100,
+ align: "left",
+ bind: { key: "warehouseEnum", data: [] },
+ },
+ {
+ field: "creater",
+ title: TEXT.creator,
+ type: "string",
+ width: 90,
+ align: "left",
+ },
+ {
+ field: "createDate",
+ title: TEXT.createDate,
+ type: "datetime",
+ width: 160,
+ align: "left",
+ },
+ {
+ field: "modifier",
+ title: TEXT.modifier,
+ type: "string",
+ width: 100,
+ align: "left",
+ hidden: true,
+ },
+ {
+ field: "modifyDate",
+ title: TEXT.modifyDate,
+ type: "datetime",
+ width: 160,
+ align: "left",
+ hidden: true,
+ },
+ ]);
+
+ const detail = ref({
+ cnName: "#detailCnName",
+ table: "",
+ columns: [],
+ sortName: "",
+ });
+
+ const detailState = reactive({
+ rowsMap: {},
+ loadingMap: {},
+ errorMap: {},
+ });
+
+ const stockStatusOptions = ref([]);
+
+ const detailColumns = [
+ { field: "materielName", title: TEXT.materielName, minWidth: 160 },
+ { field: "serialNumber", title: TEXT.serialNumber, minWidth: 160 },
+ { field: "stockQuantity", title: TEXT.stockQuantity, minWidth: 120 },
+ { field: "status", title: TEXT.status, minWidth: 120 },
+ { field: "inboundOrderRowNo", title: TEXT.inboundOrderRowNo, minWidth: 120 },
+ ];
+
+ const normalizeValue = (value) => {
+ return value === null || value === undefined || value === "" ? "--" : value;
+ };
+
+ const formatStatusText = (value) => {
+ const matched = stockStatusOptions.value.find((item) => `${item.key}` === `${value}`);
+ return matched ? matched.value || matched.label : normalizeValue(value);
+ };
+
+ const getDetailRows = (stockId) => {
+ return detailState.rowsMap[stockId] || [];
+ };
+
+ const loadDetailRows = async (row) => {
+ if (!row || !row.id || detailState.loadingMap[row.id]) {
+ return;
+ }
+ if (detailState.rowsMap[row.id]) {
+ return;
+ }
+
+ detailState.loadingMap[row.id] = true;
+ detailState.errorMap[row.id] = "";
+ try {
+ const result = await proxy.http.post("/api/StockInfoDetail/getPageData", {
+ page: 1,
+ rows: 200,
+ sort: "id",
+ order: "asc",
+ wheres: JSON.stringify([
+ {
+ name: "stockId",
+ value: String(row.id),
+ displayType: "int",
+ },
+ ]),
+ });
+ detailState.rowsMap[row.id] = (result && result.rows) || [];
+ } catch (error) {
+ detailState.rowsMap[row.id] = null;
+ detailState.errorMap[row.id] = error?.message || TEXT.detailLoadFailed;
+ } finally {
+ detailState.loadingMap[row.id] = false;
+ }
+ };
+
+ const loadStockStatusOptions = async () => {
+ try {
+ const result = await proxy.http.post("/api/Sys_Dictionary/GetVueDictionary", ["stockStatusEmun"]);
+ const matched = (result || []).find((item) => item.dicNo === "stockStatusEmun");
+ stockStatusOptions.value = matched ? matched.data || [] : [];
+ } catch (error) {
+ stockStatusOptions.value = [];
+ }
+ };
+
+ loadStockStatusOptions();
+
+ const renderStatus = (row) => {
+ if (detailState.loadingMap[row.id]) {
+ return h("div", { class: "stock-detail-status" }, TEXT.detailLoading);
+ }
+ if (detailState.errorMap[row.id]) {
+ return h(
+ "div",
+ { class: "stock-detail-status stock-detail-status--error" },
+ detailState.errorMap[row.id]
+ );
+ }
+ return null;
+ };
+
+ const renderDetailTable = (row) => {
+ const statusNode = renderStatus(row);
+ if (statusNode) {
+ return statusNode;
+ }
+
+ const rows = getDetailRows(row.id);
+ if (!rows.length) {
+ return h("div", { class: "stock-detail-status" }, TEXT.detailEmpty);
+ }
+
+ return h("div", { class: "stock-detail-table-wrapper" }, [
+ h("div", { class: "stock-detail-toolbar" }, [
+ h("div", { class: "stock-detail-toolbar__left" }, TEXT.detailName),
+ h("div", { class: "stock-detail-toolbar__right" }, [
+ h("span", { class: "stock-detail-count" }, `${rows.length} 鏉),
+ ]),
+ ]),
+ h(
+ ElTable,
+ {
+ data: rows,
+ border: true,
+ stripe: true,
+ size: "small",
+ class: "stock-detail-el-table",
+ maxHeight: 420,
+ emptyText: TEXT.detailEmpty,
+ },
+ () =>
+ detailColumns.map((column) =>
+ h(ElTableColumn, {
+ key: column.field,
+ prop: column.field,
+ label: column.title,
+ minWidth: column.minWidth,
+ showOverflowTooltip: true,
+ formatter: (detailRow) =>
+ column.field === "status"
+ ? formatStatusText(detailRow[column.field])
+ : normalizeValue(detailRow[column.field]),
+ })
+ )
+ ),
]);
- const searchFormFields = ref({
- palletCode: "",
- locationCode: "",
- });
- const searchFormOptions = ref([
- [
- { title: "鎵樼洏缂栧彿", field: "palletCode" },
- { title: "璐т綅缂栧彿", field: "locationCode" },
- ],
- ]);
- const columns = ref([
- {
- field: "id",
- title: "Id",
- type: "int",
- width: 90,
- hidden: true,
- readonly: true,
- require: true,
- align: "left",
- },
- {
- field: "palletCode",
- title: "鎵樼洏缂栧彿",
- type: "string",
- width: 90,
- align: "left",
- },
- {
- field: "locationCode",
- title: "璐т綅缂栧彿",
- type: "string",
- width: 150,
- align: "left",
- },
- // {
- // field: "isFull",
- // title: "鏄惁婊$洏",
- // type: "string",
- // width: 150,
- // align: "left",
- // bind: { key: "yesno", data: [] },
- // },
- {
- field: "warehouseId",
- title: "浠撳簱",
- type: "select",
- width: 100,
- align: "left",
- bind: { key: "warehouseEnum", data: [] },
- },
- {
- field: "creater",
- title: "鍒涘缓浜�",
- type: "string",
- width: 90,
- align: "left",
- },
- {
- field: "createDate",
- title: "鍒涘缓鏃堕棿",
- type: "datetime",
- width: 160,
- align: "left",
- },
- {
- field: "modifier",
- title: "淇敼浜�",
- type: "string",
- width: 100,
- align: "left",
- hidden:true
- },
- {
- field: "modifyDate",
- title: "淇敼鏃堕棿",
- type: "datetime",
- width: 160,
- align: "left",
- hidden:true
- },
- {
- field: "remark",
- title: "澶囨敞",
- type: "string",
- width: 100,
- align: "left",
- hidden:true
- },
- ]);
- const detail = ref({
- cnName: "#detailCnName",
- table: "",
- columns: [],
- sortName: "",
- });
- return {
- table,
- extend,
- editFormFields,
- editFormOptions,
- searchFormFields,
- searchFormOptions,
- columns,
- detail,
- };
- },
- });
- </script>
-
\ No newline at end of file
+ };
+
+ const tableExpand = ref({
+ width: 55,
+ onChange(row, expandedRows) {
+ const isExpanded = expandedRows.some((item) => item.id === row.id);
+ if (isExpanded) {
+ loadDetailRows(row);
+ }
+ },
+ render(render, { row }) {
+ return render("div", { class: "stock-detail-panel" }, [
+ render("div", { class: "stock-detail-header" }, [
+ render("div", { class: "stock-detail-header__main" }, [
+ render("div", { class: "stock-detail-title" }, TEXT.detailName),
+ render(
+ "div",
+ { class: "stock-detail-subtitle" },
+ `${TEXT.expandPrefix}${normalizeValue(row.palletCode)}${TEXT.expandMiddle}${TEXT.expandLocation}${normalizeValue(row.locationCode)}`
+ ),
+ ]),
+ // render("div", { class: "stock-detail-tags" }, [
+ // render("span", { class: "stock-detail-tag" }, normalizeValue(row.palletCode)),
+ // render(
+ // "span",
+ // { class: "stock-detail-tag stock-detail-tag--muted" },
+ // normalizeValue(row.locationCode)
+ // ),
+ // ]),
+ ]),
+ renderDetailTable(row),
+ ]);
+ },
+ });
+
+ return {
+ table,
+ extend,
+ editFormFields,
+ editFormOptions,
+ searchFormFields,
+ searchFormOptions,
+ columns,
+ detail,
+ tableExpand,
+ };
+ },
+});
+</script>
+
+<style scoped>
+.stock-detail-panel {
+ margin: 4px 8px 12px;
+ padding: 14px 16px 16px;
+ background: linear-gradient(180deg, #ffffff 0%, #fafbfc 100%);
+ border: 1px solid #e8edf3;
+ border-radius: 10px;
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
+}
+
+.stock-detail-header {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ gap: 12px;
+ margin-bottom: 12px;
+ padding-bottom: 12px;
+ border-bottom: 1px solid #edf1f5;
+}
+
+.stock-detail-header__main {
+ min-width: 0;
+}
+
+.stock-detail-title {
+ margin-bottom: 4px;
+ font-size: 15px;
+ font-weight: 700;
+ color: #303133;
+}
+
+.stock-detail-subtitle {
+ font-size: 13px;
+ color: #606266;
+ line-height: 1.6;
+}
+
+.stock-detail-tags {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: flex-end;
+ gap: 8px;
+}
+
+.stock-detail-tag {
+ display: inline-flex;
+ align-items: center;
+ height: 28px;
+ padding: 0 10px;
+ color: #1f5eff;
+ background: #edf4ff;
+ border: 1px solid #d8e6ff;
+ border-radius: 999px;
+ font-size: 12px;
+ font-weight: 600;
+}
+
+.stock-detail-tag--muted {
+ color: #4e5969;
+ background: #f4f6f8;
+ border-color: #e5e9ef;
+}
+
+.stock-detail-status {
+ padding: 14px 12px;
+ color: #606266;
+ background: #f8fafc;
+ border: 1px dashed #d9e2ec;
+ border-radius: 8px;
+}
+
+.stock-detail-status--error {
+ color: #f56c6c;
+ background: #fef0f0;
+ border-color: #fde2e2;
+}
+
+.stock-detail-table-wrapper {
+ overflow-x: auto;
+ border: 1px solid #ebeef5;
+ border-radius: 8px;
+ background: #fff;
+}
+
+.stock-detail-toolbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+ padding: 12px 14px;
+ background: #f8fafc;
+ border-bottom: 1px solid #edf1f5;
+}
+
+.stock-detail-toolbar__left {
+ font-size: 13px;
+ font-weight: 600;
+ color: #303133;
+}
+
+.stock-detail-count {
+ display: inline-flex;
+ align-items: center;
+ height: 24px;
+ padding: 0 10px;
+ color: #606266;
+ background: #fff;
+ border: 1px solid #e5e9ef;
+ border-radius: 999px;
+ font-size: 12px;
+}
+
+:deep(.stock-detail-el-table) {
+ border-top: none;
+}
+
+:deep(.stock-detail-el-table .el-table__inner-wrapper::before) {
+ display: none;
+}
+
+:deep(.stock-detail-el-table th.el-table__cell) {
+ background: #f5f7fa;
+ color: #303133;
+ font-weight: 600;
+}
+
+:deep(.stock-detail-el-table td.el-table__cell) {
+ color: #606266;
+}
+
+:deep(.stock-detail-el-table .el-table__body tr:hover > td.el-table__cell) {
+ background: #f0f7ff;
+}
+</style>
diff --git "a/\351\241\271\347\233\256\350\265\204\346\226\231/\350\256\276\345\244\207\345\215\217\350\256\256/\346\213\230\346\235\237\346\234\272\345\257\271\346\216\245\345\215\217\350\256\256/\346\213\230\346\235\237\346\234\272\345\257\271\346\216\245\345\215\217\350\256\256.xlsx" "b/\351\241\271\347\233\256\350\265\204\346\226\231/\350\256\276\345\244\207\345\215\217\350\256\256/\346\213\230\346\235\237\346\234\272\345\257\271\346\216\245\345\215\217\350\256\256/\346\213\230\346\235\237\346\234\272\345\257\271\346\216\245\345\215\217\350\256\256.xlsx"
new file mode 100644
index 0000000..dc2b088
--- /dev/null
+++ "b/\351\241\271\347\233\256\350\265\204\346\226\231/\350\256\276\345\244\207\345\215\217\350\256\256/\346\213\230\346\235\237\346\234\272\345\257\271\346\216\245\345\215\217\350\256\256/\346\213\230\346\235\237\346\234\272\345\257\271\346\216\245\345\215\217\350\256\256.xlsx"
Binary files differ
--
Gitblit v1.9.3