From b0b5deb5825684bca5b3fa7c2ab59f60ce0e799f Mon Sep 17 00:00:00 2001
From: xiazhengtongxue <133085197+xiazhengtongxue@users.noreply.github.com>
Date: 星期二, 07 四月 2026 16:36:57 +0800
Subject: [PATCH] fix: 修复移库任务号重复问题,优化策略优先处理正常任务,避免任务堵塞
---
项目代码/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs | 337 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 327 insertions(+), 10 deletions(-)
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs"
index f3a3025..81c2bb2 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs"
@@ -1,4 +1,5 @@
锘縰sing HslCommunication.WebSocket;
+using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using SqlSugar;
@@ -10,6 +11,7 @@
using WIDESEA_Common.CommonEnum;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.StockEnum;
+using WIDESEA_Common.WareHouseEnum;
using WIDESEA_Core;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
@@ -20,6 +22,7 @@
using WIDESEA_Core.Seed;
using WIDESEA_Core.Utilities;
using WIDESEA_DTO.Basic;
+using WIDESEA_DTO.Task;
using WIDESEA_IBasicService;
using WIDESEA_Model.Models;
@@ -30,6 +33,9 @@
private readonly IUnitOfWorkManage _unitOfWorkManage;
private readonly IRepository<Dt_StockInfo> _stockInfoRepository;
public IRepository<Dt_LocationInfo> Repository => BaseDal;
+ private readonly static object _locker = new object();
+
+ public static List<LocationCache> locationCaches = new List<LocationCache>();
public LocationInfoService(IRepository<Dt_LocationInfo> BaseDal, IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_StockInfo> stockInfoRepository) : base(BaseDal)
{
@@ -153,24 +159,335 @@
return WebResponseContent.Instance.Error(ex.Message);
}
}
-
-
- public string AccessingTunnel(int WarehouseId, int LocationType)
+
+
+ public string AccessingTunnel(int WarehouseId, int LocationType, List<RoadwayTaskCount> roadwayTaskCounts)
{
List<Dt_LocationInfo> locationData = BaseDal.QueryData(x => x.WarehouseId == WarehouseId);
- var roadwayGroups = locationData
- .Where(x => x.LocationType == LocationType)
+
+ // 灏� roadwayTaskCounts 杞崲涓哄瓧鍏革紝渚夸簬蹇�熸煡鎵�
+ var taskCountDict = roadwayTaskCounts?.ToDictionary(x => x.Roadway, x => x.TaskCount) ?? new Dictionary<string, int>();
+
+ var roadwayGroups = locationData.Where(x => x.LocationType == LocationType && x.LocationStatus == (int)LocationStatusEnum.Free && x.EnableStatus == (int)EnableStatusEnum.Normal)
.GroupBy(x => x.RoadwayNo)
.Select(g => new
{
RoadwayNo = g.Key,
- LocationCount = g.Count(),
- AllLocations = g.ToList()
+ FreeCount = g.Count(),
+ TaskCount = taskCountDict.ContainsKey(g.Key) ? taskCountDict[g.Key] : 0,
+ AvailableCount = g.Count() - (taskCountDict.ContainsKey(g.Key) ? taskCountDict[g.Key] : 0)
})
- .OrderByDescending(g => g.LocationCount) // 鏀逛负闄嶅簭鎺掑簭
- .FirstOrDefault(); // 鍙栫涓�涓紙鏁伴噺鏈�澶氱殑锛�
+ .Where(g => g.AvailableCount > 0)
+ .ToList();
- return roadwayGroups.RoadwayNo;
+ int minRequired = 3;
+
+ if (WarehouseId == (int)WarehouseEnum.YMYL)
+ {
+ if (LocationType == 2) minRequired = 2;
+
+ // 杩欓噷閫夋嫨宸烽亾1鎴栬��2锛屽厛鎵句换鍔℃渶灏戠殑锛屽鏋滀竴鏍凤紝閫夋嫨搴撳瓨鍦ㄥ鐨�
+ var targetRoadways = roadwayGroups
+ .Where(g => (g.RoadwayNo == "1" || g.RoadwayNo == "2") && g.AvailableCount >= minRequired)
+ .OrderBy(g => g.TaskCount) // 鍏堟寜浠诲姟鏁板崌搴忥紙浠诲姟灏戠殑浼樺厛锛�
+ .ThenByDescending(g => g.FreeCount) // 浠诲姟鐩稿悓鏃舵寜绌洪棽鏁伴檷搴忥紙搴撳瓨澶氱殑浼樺厛锛�
+ .ToList();
+
+ var selectedRoadway = targetRoadways.FirstOrDefault();
+ if (selectedRoadway != null)
+ return selectedRoadway.RoadwayNo;
+ }
+ else
+ {
+ // 杩欓噷閫夋嫨宸烽亾3鎴栬��4鎴栬��5锛屽厛鎵句换鍔℃渶灏戠殑锛屽鏋滀竴鏍凤紝閫夋嫨搴撳瓨鍦ㄥ鐨�
+ var targetRoadways = roadwayGroups
+ .Where(g => (g.RoadwayNo == "3" || g.RoadwayNo == "4" || g.RoadwayNo == "5") && g.AvailableCount >= minRequired)
+ .OrderBy(g => g.TaskCount) // 鍏堟寜浠诲姟鏁板崌搴忥紙浠诲姟灏戠殑浼樺厛锛�
+ .ThenByDescending(g => g.FreeCount) // 浠诲姟鐩稿悓鏃舵寜绌洪棽鏁伴檷搴忥紙搴撳瓨澶氱殑浼樺厛锛�
+ .ToList();
+
+ var selectedRoadway = targetRoadways.FirstOrDefault();
+ if (selectedRoadway == null)
+ {
+ // 濡傛灉娌℃湁婊¤冻鏈�浣庤姹傜殑锛屽皾璇曢�夋嫨宸烽亾5锛堝彧瑕佹湁鍙敤搴撲綅灏辫锛�
+ selectedRoadway = roadwayGroups
+ .Where(g => g.RoadwayNo == "5" && g.AvailableCount > 0)
+ .FirstOrDefault();
+ }
+
+ if (selectedRoadway != null)
+ return selectedRoadway.RoadwayNo;
+ }
+
+ return "0";
+ }
+
+
+
+ public Dt_LocationInfo? ShallowGetLocation(string roadway, int Locationtype,int row ,int Layer, int Column)
+ {
+ return BaseDal.QueryData(x => x.RoadwayNo == roadway && x.LocationType == Locationtype && x.Row==row && x.Layer== Layer && x.Column== Column).FirstOrDefault();
+ }
+
+ public Dt_LocationInfo? FindStorageLocation(string LocationCode)
+ {
+ return BaseDal.QueryData(x => x.LocationCode == LocationCode).FirstOrDefault();
+ }
+
+
+ //鏌ユ壘鏂拌揣浣�
+ public Dt_LocationInfo? GetLocation(string roadway, int Locationtype)
+ {
+ lock (_locker)
+ {
+ List<LocationCache> removeItems = locationCaches.Where(x => (DateTime.Now - x.DateTime).TotalMinutes > 5).ToList();//鏌ヨ娣诲姞闈欐�佸彉閲忚秴杩�10鍒嗛挓鐨勮揣浣�
+ int count = removeItems.Count;
+ for (int i = 0; i < count; i++)
+ {
+ locationCaches.Remove(removeItems[i]);//绉婚櫎鏌ヨ娣诲姞闈欐�佸彉閲忚秴杩�5鍒嗛挓鐨勮揣浣�
+ }
+
+ List<string> lockLocations = locationCaches.Select(x => x.LocationCode).ToList();
+
+ List<Dt_LocationInfo> locationInfos = null;
+ locationInfos = BaseDal.QueryData(x => x.RoadwayNo == roadway && x.LocationType == Locationtype && x.EnableStatus == (int)EnableStatusEnum.Normal);
+
+
+ List<Dt_LocationInfo> emptyLocations = locationInfos.Where(x => x.LocationStatus == LocationStatusEnum.Free.ObjToInt() && !lockLocations.Contains(x.LocationCode)).OrderBy(x => x.Layer).ThenBy(x => x.Column).ThenByDescending(x => x.Depth).ThenBy(x => x.Row).ToList();//鏌ヨ绌鸿揣浣嶄俊鎭苟鎺掗櫎20鍒嗛挓鍐呭垎閰嶇殑璐т綅,鏍规嵁灞傘�佸垪銆佹繁搴︺�佽鎺掑簭
+
+
+ for (int i = 0; i < emptyLocations.Count; i++)
+ {
+ if (emptyLocations[i].Depth == 1)//鍒ゆ柇鏄惁1娣辫揣浣�
+ {
+ //鏌ヨ娣卞簱浣�
+ //int emprow = emptyLocations[i].Row == 2 ? 1 : 4;
+ int emprow = judgmentRow(emptyLocations[i].RoadwayNo,emptyLocations[i].Row);
+
+ Dt_LocationInfo? sencondDepthLocationShen = emptyLocations.FirstOrDefault(x => x.Row == emprow && x.Layer == emptyLocations[i].Layer && x.Column == emptyLocations[i].Column);
+ if (sencondDepthLocationShen != null && sencondDepthLocationShen.LocationStatus == LocationStatusEnum.Free.ObjToInt())
+ {
+ locationCaches.Add(new LocationCache { DateTime = DateTime.Now, LocationCode = sencondDepthLocationShen.LocationCode });
+ return sencondDepthLocationShen;//1娣辫揣浣嶅強2娣辫揣浣嶉兘涓虹┖鐨勬儏鍐典笅,浼樺厛鍒嗛厤2娣辫揣浣�
+ }
+ else
+ {
+ Dt_LocationInfo? sencondDepthLo = locationInfos.FirstOrDefault(x => x.Row == emprow && x.Layer == emptyLocations[i].Layer && x.Column == emptyLocations[i].Column);
+ if (sencondDepthLo != null && sencondDepthLo.LocationStatus != LocationStatusEnum.Lock.ObjToInt() && sencondDepthLo.LocationStatus == LocationStatusEnum.InStock.ObjToInt() && !lockLocations.Contains(sencondDepthLo.LocationCode))
+ {
+ locationCaches.Add(new LocationCache { DateTime = DateTime.Now, LocationCode = emptyLocations[i].LocationCode });
+ return emptyLocations[i];
+ }else if (emptyLocations[i].RoadwayNo=="5" && emptyLocations[i].LocationStatus == LocationStatusEnum.Free.ObjToInt())
+ {
+ locationCaches.Add(new LocationCache { DateTime = DateTime.Now, LocationCode = emptyLocations[i].LocationCode });
+ return emptyLocations[i];
+ }
+ }
+ }
+ else
+ {
+ //鏌ヨ2娣辫揣浣嶅搴旂殑1娣辫揣浣嶆槸鍚︿负绌�
+ //int emprow = emptyLocations[i].Row == 4 ? 3 : 2;
+ int emprow = judgmentRow(emptyLocations[i].RoadwayNo, emptyLocations[i].Row);
+
+ Dt_LocationInfo? sencondDepthLocationQian = emptyLocations.FirstOrDefault(x => x.Row == emprow && x.Layer == emptyLocations[i].Layer && x.Column == emptyLocations[i].Column);
+ if (sencondDepthLocationQian != null && sencondDepthLocationQian.LocationStatus == LocationStatusEnum.Free.ObjToInt())
+ {
+ locationCaches.Add(new LocationCache { DateTime = DateTime.Now, LocationCode = emptyLocations[i].LocationCode });
+ return emptyLocations[i];
+ }
+ }
+ }
+ return null;
+ }
+ }
+
+ public int judgmentRow(string RoadwayNo, int locrow)
+ {
+ if (RoadwayNo == "1" || RoadwayNo == "3")
+ {
+ if(locrow==1 || locrow == 4)
+ {
+ return locrow == 1 ? 2 : 3;
+ }
+ else
+ {
+ return locrow == 2 ? 1 : 4;
+ }
+
+ }
+ else if (RoadwayNo == "2" || RoadwayNo == "4")
+ {
+ if (locrow == 5 || locrow == 8)
+ {
+ return locrow == 5 ? 6 : 7;
+ }
+ else
+ {
+ return locrow == 6 ? 5 : 8;
+ }
+
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ public class LocationCache
+ {
+ public string LocationCode { get; set; }
+
+ public DateTime DateTime { get; set; }
+ }
+
+
+
+ public WebResponseContent GetArea()
+ {
+ // WarehouseId鍒嗙粍锛岀劧鍚庢槸RoadwayNo
+ var result = BaseDal.QueryData()
+ .GroupBy(x => x.WarehouseId)
+ .Select(g => new {
+ WarehouseId = g.Key,
+ RoadwayNo = g.Select(x => x.RoadwayNo).Distinct().ToList()
+ })
+ .ToList();
+ return WebResponseContent.Instance.OK("鎴愬姛", result);
+ }
+
+ public WebResponseContent GetLocationStatus(int WarehouseId, string RoadwayNo)
+ {
+ // 鏍煎紡{灞�,{杩欎竴灞傜殑鍒楁暟鎹畗}
+ var locations = BaseDal.QueryData(x => x.WarehouseId == WarehouseId && x.RoadwayNo == RoadwayNo)
+ .Select(x => new
+ {
+ x.RoadwayNo,
+ x.LocationCode,
+ x.WarehouseId,
+ x.Row,
+ x.Column,
+ x.Layer,
+ x.Depth,
+ x.LocationType,
+ x.LocationStatus,
+ x.EnableStatus
+ })
+ .ToList();
+
+ // 濡傛灉娌℃湁鎵惧埌鏁版嵁锛岃繑鍥炵┖鍒楄〃鑰屼笉鏄痭ull
+ if (locations == null || !locations.Any())
+ {
+ return WebResponseContent.Instance.OK("鏈壘鍒板搴斿贩閬撶殑璐т綅鏁版嵁", new List<object>());
+ }
+
+ // 淇敼涓哄眰涓嬮潰鏀炬墍鏈夊垪鐨勪俊鎭�
+ var result = locations
+ .GroupBy(x => x.Layer) // 鎸夊眰鍒嗙粍
+ .Select(layerGroup => new
+ {
+ layer = layerGroup.Key,
+ columns = layerGroup.GroupBy(x => x.Column) // 姣忓眰涓寜鍒楀垎缁�
+ .Select(columnGroup => new
+ {
+ column = columnGroup.Key,
+ depths = columnGroup.Select(d => new
+ {
+ row = d.Row,
+ LocationCode = d.LocationCode,
+ depth = d.Depth,
+ locationType = d.LocationType,
+ locationStatus = d.LocationStatus,
+ enableStatus = d.EnableStatus
+ }).ToList()
+ }).ToList()
+ }).ToList();
+
+ return WebResponseContent.Instance.OK("鎴愬姛", result);
+ }
+ // 缁х画鍒嗭紝WarehouseId =1锛屾湁涓や釜涓嶅悓鐨勮揣鐗╋紝LocationType =1鍜�2
+ public WebResponseContent GetWarehouseCapacity()
+ {
+ // 鏌ヨ鎵�鏈変粨搴撶殑璐т綅鏁版嵁锛屽寘鍚揣浣嶇被鍨�
+ var allLocations = BaseDal.QueryData()
+ .Select(x => new
+ {
+ x.WarehouseId,
+ x.LocationStatus,
+ x.LocationType // 娣诲姞璐т綅绫诲瀷
+ })
+ .ToList();
+
+ // 濡傛灉娌℃湁鏁版嵁锛岃繑鍥炵┖鍒楄〃
+ if (allLocations == null || !allLocations.Any())
+ {
+ return WebResponseContent.Instance.OK("鏈壘鍒颁换浣曡揣浣嶆暟鎹�", new List<object>());
+ }
+
+ // 鎸変粨搴撳拰璐т綅绫诲瀷鍒嗙粍缁熻
+ var result = allLocations
+ .GroupBy(x => new { x.WarehouseId, x.LocationType })
+ .Select(g => new
+ {
+ WarehouseId = g.Key.WarehouseId,
+ LocationType = g.Key.LocationType,
+ TotalLocations = g.Count(),
+ FreeLocations = g.Count(x => x.LocationStatus == 0),
+ UsedLocations = g.Count(x => x.LocationStatus == 1),
+ OccupancyRate = (int)Math.Round((double)g.Count(x => x.LocationStatus == 1) / g.Count() * 100),
+ RemainingCapacityPercentage = (int)Math.Round((double)g.Count(x => x.LocationStatus == 0) / g.Count() * 100)
+ })
+ .OrderBy(x => x.WarehouseId)
+ .ThenBy(x => x.LocationType)
+ .ToList();
+
+ return WebResponseContent.Instance.OK("鎴愬姛", result);
+ }
+
+ /// <summary>
+ /// 涓�閿惎鐢ㄥ贩閬撴墍鏈夎揣浣�
+ /// </summary>
+ /// <param name="warehouseId">浠撳簱ID</param>
+ /// <param name="roadwayNo">宸烽亾缂栧彿</param>
+ /// <returns></returns>
+ public WebResponseContent EnableAllLocationsInRoadway(string roadwayNo)
+ {
+ if (string.IsNullOrEmpty(roadwayNo))
+ return WebResponseContent.Instance.Error("宸烽亾缂栧彿涓嶈兘涓虹┖");
+
+ var locations = Repository.QueryData(x =>
+ x.RoadwayNo == roadwayNo &&
+ x.EnableStatus != EnableStatusEnum.Normal.ObjToInt());
+
+ if (locations == null || locations.Count == 0)
+ return WebResponseContent.Instance.OK("璇ュ贩閬撴病鏈夐渶瑕佸惎鐢ㄧ殑璐т綅");
+
+ locations.ForEach(x => x.EnableStatus = EnableStatusEnum.Normal.ObjToInt());
+ Repository.UpdateData(locations);
+
+ return WebResponseContent.Instance.OK($"鎴愬姛鍚敤宸烽亾[{roadwayNo}]鐨剓locations.Count}涓揣浣�");
+ }
+
+ /// <summary>
+ /// 涓�閿鐢ㄥ贩閬撴墍鏈夎揣浣�
+ /// </summary>
+ /// <param name="warehouseId">浠撳簱ID</param>
+ /// <param name="roadwayNo">宸烽亾缂栧彿</param>
+ /// <returns></returns>
+ public WebResponseContent DisableAllLocationsInRoadway(string roadwayNo)
+ {
+ if (string.IsNullOrEmpty(roadwayNo))
+ return WebResponseContent.Instance.Error("宸烽亾缂栧彿涓嶈兘涓虹┖");
+ var locations = Repository.QueryData(x =>
+ x.RoadwayNo == roadwayNo &&
+ x.EnableStatus != EnableStatusEnum.Disable.ObjToInt());
+ if (locations == null || locations.Count == 0)
+ return WebResponseContent.Instance.OK("璇ュ贩閬撴病鏈夐渶瑕佺鐢ㄧ殑璐т綅");
+ // 妫�鏌ヨ揣浣嶆槸鍚︽湁搴撳瓨
+ var locationIds = locations.Select(x => x.Id).ToList();
+ locations.ForEach(x => x.EnableStatus = EnableStatusEnum.Disable.ObjToInt());
+ Repository.UpdateData(locations);
+ return WebResponseContent.Instance.OK($"鎴愬姛绂佺敤宸烽亾[{roadwayNo}]鐨剓locations.Count}涓揣浣�");
}
}
}
--
Gitblit v1.9.3