ÏîÄ¿´úÂë/WMS/WIDESEA_WMSServer/WIDESEA_StorageTaskServices/Task/Dt_TaskService.cs
@@ -1,16 +1,22 @@
using Mapster;
using AngleSharp.Dom;
using log4net.Core;
using Mapster;
using Masuit.Tools;
using OfficeOpenXml.Table.PivotTable;
using SixLabors.Fonts.Tables.AdvancedTypographic;
using SqlSugar;
using System;
using System.Reflection.Metadata;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using WIDESEA_Cache;
using WIDESEA_Common;
using WIDESEA_Core.Const;
using WIDESEA_DTO.Location;
using WIDESEA_DTO.WMS;
using WIDESEA_IServices;
using WIDESEA_Model.Models;
using WIDESEA_Model.Models.Basic;
using WIDESEAWCS_BasicInfoRepository;
using WIDESEAWCS_QuartzJob.Models;
@@ -31,7 +37,6 @@
    private readonly IDt_AreaInfoRepository _areaInfoRepository; //区域
    private readonly IDt_StationManagerRepository _stationManagerRepository;
    private readonly ISys_ConfigService _configService;
    private readonly ISimpleCacheService _simpleCacheService;
    public Dt_TaskService(IDt_TaskRepository BaseDal,
                                IUnitOfWorkManage unitOfWorkManage,
@@ -45,8 +50,7 @@
                                IDt_AreaInfoRepository areaInfoRepository,
                                IStockInfoDetailRepository stockInfoDetailRepository,
                                IDt_StationManagerRepository stationManagerRepository,
                                ISys_ConfigService configService,
                                ISimpleCacheService simpleCacheService) : base(BaseDal)
                                ISys_ConfigService configService) : base(BaseDal)
    {
        _unitOfWorkManage = unitOfWorkManage;
        _stockInfoRepository = stockInfoRepository;
@@ -60,7 +64,6 @@
        _stockInfoDetailRepository = stockInfoDetailRepository;
        _stationManagerRepository = stationManagerRepository;
        _configService = configService;
        _simpleCacheService = simpleCacheService;
    }
    #region å¤–部接口方法
@@ -72,7 +75,16 @@
        WebResponseContent content = new WebResponseContent();
        try
        {
            task.TaskState = (int)TaskOutStatusEnum.OutFinish;
            var taskHty = task.Adapt<Dt_Task_Hty>();
            taskHty.FinishTime = DateTime.Now;
            taskHty.OperateType = App.User.UserName != null ? (int)OperateTypeEnum.人工完成 : (int)OperateTypeEnum.自动完成;
            taskHty.Creater = App.User.UserName != null ? App.User.UserName : "System";
            await _unitOfWorkManage.UseTranAsync(async () =>
            {
                await DeleteTaskAsync(task.TaskId);
                await AddTaskHtyAsync(taskHty);
            });
        }
        catch (Exception ex)
        {
@@ -81,6 +93,788 @@
        return content;
    }
    #endregion å‡ºåº“任务完成
    #region ç§»åº“任务完成
    /// <summary>
    /// ç§»åº“任务完成
    /// </summary>
    /// <param name="saveModel">任务数据合集</param>
    /// <returns>返回结果集</returns>
    public async Task<WebResponseContent> CompleteTransferTaskAsync(Dt_Task task, DtStockInfo stock)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            // æ›´æ–°è´§ä½å’Œåº“存信息
            (DtStockInfo updateStock, DtLocationInfo locationInForm, DtLocationInfo locationInfoTo) = UpdateStockLocation(stock, task);
            var taskHty = CreateHistoricalTask(task);
            LogFactory.GetLog("任务完成").InfoFormat(true, "移库任务完成", $"货位地址:{task.TargetAddress},修改后库存数据:{JsonConvert.SerializeObject(updateStock)},原先货位数据:{locationInForm}");
            // æ‰§è¡Œæ•°æ®åº“事务
            bool isResult = false;
            if (isResult)
                content.OK("移库任务完成成功");
            else
                content.Error("移库任务完成失败");
        }
        catch (Exception err)
        {
            Console.WriteLine(err.Message.ToString());
        }
        return content;
    }
    #endregion ç§»åº“任务完成
    #region å…¥åº“任务完成
    /// <summary>
    /// å®Œæˆå…¥åº“任务
    /// </summary>
    /// <param name="task">任务数据合集</param>
    /// <returns>返回结果集</returns>
    public async Task<WebResponseContent> CompleteInboundTaskAsync(Dt_Task task)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            task.TaskState = (int)TaskInStatusEnum.InFinish;
            var taskHty = task.Adapt<Dt_Task_Hty>();
            taskHty.FinishTime = DateTime.Now;
            taskHty.OperateType = App.User.UserName != null ? (int)OperateTypeEnum.人工完成 : (int)OperateTypeEnum.自动完成;
            taskHty.Creater = App.User.UserName != null ? App.User.UserName : "System";
            await _unitOfWorkManage.UseTranAsync(async () =>
            {
                await DeleteTaskAsync(task.TaskId);
                await AddTaskHtyAsync(taskHty);
            });
        }
        catch (Exception ex)
        {
            return content.Error(ex.Message);
        }
        return content;
    }
    #endregion å…¥åº“任务完成
    #region AGV搬运任务完成
    public async Task<WebResponseContent> CompleteCarryTaskAsync(Dt_Task task,DtStockInfo stockInfo)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            task.TaskState = (int)TaskAGVCarryStatusEnum.CarryFinish;
            var taskHty = task.Adapt<Dt_Task_Hty>();
            taskHty.FinishTime = DateTime.Now;
            taskHty.OperateType = App.User.UserName != null ? (int)OperateTypeEnum.人工完成 : (int)OperateTypeEnum.自动完成;
            taskHty.Creater = App.User.UserName != null ? App.User.UserName : "System";
            await _unitOfWorkManage.UseTranAsync(async () =>
            {
                await DeleteTaskAsync(task.TaskId);
                await AddTaskHtyAsync(taskHty);
            });
        }
        catch (Exception ex)
        {
            return content.Error(ex.Message);
        }
        return content;
    }
    #endregion
    #region AGV跨楼层任务完成
    public async Task<WebResponseContent> CompleteAcrossFloorTaskAsync(Dt_Task task, DtStockInfo stockInfo)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            task.TaskState = (int)TaskAcrossFloorStatusEnum.CarryFinish;
            var taskHty = task.Adapt<Dt_Task_Hty>();
            taskHty.FinishTime = DateTime.Now;
            taskHty.OperateType = App.User.UserName != null ? (int)OperateTypeEnum.人工完成 : (int)OperateTypeEnum.自动完成;
            taskHty.Creater = App.User.UserName != null ? App.User.UserName : "System";
            await _unitOfWorkManage.UseTranAsync(async () =>
            {
                await DeleteTaskAsync(task.TaskId);
                await AddTaskHtyAsync(taskHty);
            });
        }
        catch (Exception ex)
        {
            return content.Error(ex.Message);
        }
        return content;
    }
    #endregion
    #region ä»»åŠ¡å®Œæˆ
    /// <summary>
    /// å®Œæˆä»»åŠ¡
    /// </summary>
    /// <param name="taskNum">任务编号</param>
    /// <returns>返回结果集</returns>
    public async Task<WebResponseContent> CompleteAsync(int taskNum)
    {
        // åˆå§‹åŒ–响应内容
        WebResponseContent content = new WebResponseContent();
        // æå–任务数据
        LogFactory.GetLog("任务完成").InfoFormat(true, "提取任务数据", $"任务号:{taskNum}");
        // éªŒè¯ä»»åŠ¡æ˜¯å¦å­˜åœ¨
        var task = await GetByTaskNum(taskNum);
        if (task == null)
        {
            return content.Error("任务不存在");
        }
        LogFactory.GetLog("任务完成").InfoFormat(true, "验证任务是否存在", JsonConvert.SerializeObject(task));
        // éªŒè¯åº“存是否存在
        var stock = await _stockInfoRepository.QueryFirstNavAsync(x => x.PalletCode == task.PalletCode);
        if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup)
        {
            return await CompleteOutboundTaskAsync(task, stock);
        }
        else if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.InboundGroup)
        {
            return await CompleteInboundTaskAsync(task);
        }
        else if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.RelocationGroup)
        {
            return await CompleteTransferTaskAsync(task, stock);
        }
        else if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.CarryGroup)
        {
            return await CompleteCarryTaskAsync(task, stock);
        }
        else if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.AcrossFloorGroup)
        {
            return await CompleteAcrossFloorTaskAsync(task, stock);
        }
        else
        {
            return content.Error("未找到任务类型");
        }
    }
    #endregion ä»»åŠ¡å®Œæˆ
    #region è¯·æ±‚任务入库
    public async Task<WebResponseContent> RequestTaskAsync(RequestTaskDto taskDto)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            var station = _stationManagerRepository.QueryFirst(x => x.stationType == 1 && x.Roadway == "SC1");
            var location = await _locationRepository.QueryFirstAsync(x => x.LocationCode == taskDto.Position);
            Dt_Task taskNew = new Dt_Task
            {
                Grade = 1,
                Roadway = "SC1",
                TargetAddress = "SC1",
                Dispatchertime = DateTime.Now,
                MaterialNo = "",
                NextAddress = station.stationChildCode,
                OrderNo = null,
                PalletCode = taskDto.PalletCode,
                SourceAddress = taskDto.Position,
                CurrentAddress = taskDto.Position,
                TaskState = (int)TaskInStatusEnum.InNew,
                TaskType = (int)TaskInboundTypeEnum.Inbound,
                TaskNum = BaseDal.GetTaskNo().Result,
                CreateDate = DateTime.Now,
                TaskId = 0,
                AGVTaskNum = GenerateUniqueId(),
                Floor = "1F",
            };
            var taskDTO = CreateListTaskDTO(taskNew);
            var isResult = await AddInBoundTaskAsync(taskNew, location);
            if (!isResult)
            {
                _unitOfWorkManage.RollbackTran();
                return content.Error("新增任务失败");
            }
            return content = await SendWCSTask(taskDTO);
        }
        catch (Exception err)
        {
            content.Error(err.Message);
        }
        return content;
    }
    #endregion è¯·æ±‚任务入库
    #region æ›´æ–°ä»»åŠ¡çŠ¶æ€
    /// <summary>
    /// æ›´æ–°ä»»åŠ¡è´§ä½
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<WebResponseContent> UpdateTaskStatus(int taskNum, int taskState)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            var task = await BaseDal.QueryFirstAsync(x => x.TaskNum == taskNum);
            if (task == null)
                return content.Error("未找到任务");
            if (taskState == (int)TaskOutStatusEnum.Line_OutFinish || taskState == (int)TaskInStatusEnum.SC_InFinish || taskState == (int)TaskRelocationStatusEnum.SC_RelocationFinish || taskState == (int)TaskAGVCarryStatusEnum.AGV_CarryFinish)
            {
                var taskHty = CreateHistoricalTask(task);
                await _unitOfWorkManage.UseTranAsync(async () =>
                {
                    var asb = await BaseDal.DeleteDataByIdAsync(task.TaskId);
                    var asbHty = await _task_HtyRepository.AddDataAsync(taskHty) > 0;
                    if (asb && asbHty)
                        content.OK();
                    else
                        throw new Exception();
                });
                content.OK();
            }
            else
            {
                task.TaskState = taskState;
                var asb = await BaseDal.UpdateDataAsync(task);
                if (asb)
                    content.OK();
                else
                    content.Error();
            }
        }
        catch (Exception ex)
        {
            content.Error(ex.Message);
        }
        return content;
    }
    public async Task<WebResponseContent> RequestLocationAsync(RequestTaskDto input)
    {
        await _semaphoreUpdate.WaitAsync();
        WebResponseContent content = new WebResponseContent();
        try
        {
            Dt_Task task = BaseDal.QueryFirst(x => x.PalletCode == input.PalletCode);
            if (task == null)
            {
                return content.Error("任务对象为空");
            }
            task.TaskState = (int)TaskInStatusEnum.Line_InFinish;
            var location = await GetEmptyLocation(task.Roadway);
            if (location == null)
            {
                return content.Error("无法获取货位信息");
            }
            int beforeStatus = location.LocationStatus;
            location.LocationStatus = (int)LocationEnum.Lock;
            task.CurrentAddress = input.Position;
            task.TargetAddress = location.LocationCode;
            task.NextAddress = location.LocationCode;
            task.TaskState = (int)TaskInStatusEnum.Line_InFinish;
            // å¼€å§‹äº‹åŠ¡
            var isResult = await UpdateTaskAsync(task, location, beforeStatus);
            if (!isResult)
            {
                _unitOfWorkManage.RollbackTran();
                return content.Error("更新任务失败");
            }
            return content.OK(data: task);
        }
        catch (Exception)
        {
            throw;
        }
        finally { _semaphoreUpdate.Release(); }
    }
    #endregion
    #region è¯·æ±‚出库
    /// <summary>
    /// è¯·æ±‚托盘任务
    /// </summary>
    /// <param name="position">目标位置</param>
    /// <param name="tag">托盘类型(1:实盘,2:空盘)</param>
    /// <param name="areaCode">区域编码</param>
    /// <param name="roadways">巷道编码集合</param>
    /// <returns>返回结果集</returns>
    public async Task<WebResponseContent> RequestOutTaskAsync(RequestTaskDto taskDto)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            var station = _stationManagerRepository.QueryFirst(x => x.stationType == 1 && x.Roadway == "SC1");
            var Sourcelocation = await _locationRepository.QueryFirstAsync(x => x.LocationCode == taskDto.Position);
            DtLocationInfo Targetlocation = await GetAGVEmptyCacheLocation(2);
            Dt_Task taskNew = new Dt_Task
            {
                Grade = 1,
                Roadway = "SC1",
                TargetAddress = Targetlocation.LocationCode,
                Dispatchertime = DateTime.Now,
                MaterialNo = "",
                NextAddress = station.stationChildCode,
                OrderNo = null,
                PalletCode = taskDto.PalletCode,
                SourceAddress = taskDto.Position,
                CurrentAddress = taskDto.Position,
                TaskState = (int)TaskOutStatusEnum.OutNew,
                TaskType = (int)TaskOutboundTypeEnum.Outbound,
                TaskNum = BaseDal.GetTaskNo().Result,
                CreateDate = DateTime.Now,
                TaskId = 0,
                AGVTaskNum = GenerateUniqueId(),
                Floor = "1F",
            };
            var taskDTO = CreateListTaskDTO(taskNew);
            var isResult = await AddTaskAsync(taskNew, Sourcelocation, Targetlocation);
            if (!isResult)
            {
                _unitOfWorkManage.RollbackTran();
                return content.Error("新增任务失败");
            }
            return content = await SendWCSTask(taskDTO);
        }
        catch (Exception ex)
        {
            return content.Error(ex.Message);
        }
    }
    #endregion è¯·æ±‚出库(实盘&空盘)
    #region è¯·æ±‚跨楼层2任务
    /// <summary>
    /// è¯·æ±‚跨楼层2任务
    /// </summary>
    /// <param name="taskDto"></param>
    /// <returns></returns>
    public async Task<WebResponseContent> AcrossFloorTaskAsync(RequestAcrossFloorTaskDto taskDto)
    {
        WebResponseContent content=new WebResponseContent();
        try
        {
            var task = BaseDal.QueryFirst(x => x.TaskNum == Convert.ToInt32(taskDto.TaskNum) && x.PalletCode == taskDto.PalletCode);
            if(task == null)
                return content.Error("未找到任务");
            Dt_StationManager stationManager = new Dt_StationManager();
            if (task.Floor == "1F")
            {
                stationManager = _stationManagerRepository.QueryFirst(x => x.stationType == 5 && x.stationFloor == "2F");
            }
            else
            {
                stationManager = _stationManagerRepository.QueryFirst(x => x.stationType == 5 && x.stationFloor == "1F");
            }
            Dt_Task taskNew = new Dt_Task
            {
                Grade = 1,
                Roadway = "AGV",
                TargetAddress = task.TargetAddress,
                Dispatchertime = DateTime.Now,
                MaterialNo = "",
                NextAddress = task.TargetAddress,
                OrderNo = null,
                PalletCode = task.PalletCode,
                SourceAddress = task.SourceAddress,
                CurrentAddress = stationManager.stationChildCode,
                TaskState = (int)TaskAcrossFloorStatusEnum.SecondCarry,
                TaskType = (int)TaskAcrossFloorTypeEnum.AcrossFloorCarry,
                TaskNum = BaseDal.GetTaskNo().Result,
                CreateDate = DateTime.Now,
                TaskId = 0,
                AGVTaskNum = GenerateUniqueId(),
                Floor = stationManager.stationFloor,
            };
            var taskDTO = CreateTaskDTO(taskNew);
            var taskHty = task.Adapt<Dt_Task_Hty>();
            taskHty.FinishTime = DateTime.Now;
            taskHty.OperateType = App.User.UserName != null ? (int)OperateTypeEnum.人工完成 : (int)OperateTypeEnum.自动完成;
            taskHty.Creater = App.User.UserName != null ? App.User.UserName : "System";
            await _unitOfWorkManage.UseTranAsync(async () =>
            {
                BaseDal.AddData(taskNew);
                await DeleteTaskAsync(task.TaskId);
                await AddTaskHtyAsync(taskHty);
            });
            return content.OK(data: taskDTO);
        }
        catch (Exception ex)
        {
            return content.Error(ex.Message);
        }
    }
    #endregion
    #region è¯·æ±‚跨楼层任务
    public async Task<WebResponseContent> RequestAcrossFloorTaskAsync(RequestTaskDto taskDto)
    {
        LogFactory.GetLog("任务完成").InfoFormat(true, "移库任务完成", $"111111");
        WebResponseContent content = new WebResponseContent();
        try
        {
            var Sourcelocation = await _locationRepository.QueryFirstAsync(x => x.LocationCode == taskDto.Position);
            DtLocationInfo Targetlocation = await GetAGVEmptyCacheLocation(taskDto.AreaId);
            if (Targetlocation == null || Sourcelocation == null)
            {
                return content.Error("起点未定义或终点区域未找到空闲库位");
            }
            if (IsAcrossFloor(Sourcelocation, Targetlocation))
            {
                return content.Error("同楼层不允许请求跨楼层任务");
            }
            if (Sourcelocation != null)
            {
                var next = _stationManagerRepository.QueryFirst(x => x.stationType == 5 && x.stationFloor == Sourcelocation.Floor);
                Dt_Task taskNew = new Dt_Task
                {
                    Grade = 1,
                    Roadway = "AGV",
                    TargetAddress = Targetlocation.LocationCode,
                    Dispatchertime = DateTime.Now,
                    MaterialNo = "",
                    NextAddress = next.stationChildCode,
                    OrderNo = null,
                    PalletCode = taskDto.PalletCode,
                    SourceAddress = taskDto.Position,
                    CurrentAddress = taskDto.Position,
                    TaskState = (int)TaskAcrossFloorStatusEnum.CarryNew,
                    TaskType = (int)TaskAcrossFloorTypeEnum.AcrossFloorCarry,
                    TaskNum = BaseDal.GetTaskNo().Result,
                    CreateDate = DateTime.Now,
                    TaskId = 0,
                    AGVTaskNum = GenerateUniqueId(),
                    Floor = Sourcelocation.Floor,
                };
                var taskDTO = CreateListTaskDTO(taskNew);
                var isResult = await AddTaskAsync(taskNew, Sourcelocation, Targetlocation);
                if (!isResult)
                {
                    _unitOfWorkManage.RollbackTran();
                    return content.Error("新增任务失败");
                }
                return content = await SendWCSTask(taskDTO);
            }
            return content.Error("未找到提升机站点");
        }
        catch (Exception ex)
        {
            return content.Error(ex.Message);
        }
    }
    public async Task<WebResponseContent> RequestPointAcrossFloorTaskAsync(RequestTaskDto taskDto)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            var Sourcelocation = await _locationRepository.QueryFirstAsync(x => x.LocationCode == taskDto.Position);
            var Targetlocation = await _locationRepository.QueryFirstAsync(x => x.LocationCode == taskDto.TargetAddress);
            if (Targetlocation == null || Sourcelocation == null)
            {
                return content.Error("起点或终点未定义");
            }
            if (IsAcrossFloor(Sourcelocation, Targetlocation))
            {
                return content.Error("同楼层不允许请求跨楼层任务");
            }
            if (Sourcelocation != null)
            {
                var next = _stationManagerRepository.QueryFirst(x => x.stationType == 5 && x.stationFloor == Sourcelocation.Floor);
                Dt_Task taskNew = new Dt_Task
                {
                    Grade = 1,
                    Roadway = "AGV",
                    TargetAddress = Targetlocation.LocationCode,
                    Dispatchertime = DateTime.Now,
                    MaterialNo = "",
                    NextAddress = next.stationChildCode,
                    OrderNo = null,
                    PalletCode = taskDto.PalletCode,
                    SourceAddress = taskDto.Position,
                    CurrentAddress = taskDto.Position,
                    TaskState = (int)TaskAcrossFloorStatusEnum.CarryNew,
                    TaskType = (int)TaskAcrossFloorTypeEnum.AcrossFloorCarry,
                    TaskNum = BaseDal.GetTaskNo().Result,
                    CreateDate = DateTime.Now,
                    TaskId = 0,
                    AGVTaskNum = GenerateUniqueId(),
                    Floor = Sourcelocation.Floor,
                };
                var taskDTO = CreateListTaskDTO(taskNew);
                var isResult = await AddTaskAsync(taskNew, Sourcelocation, Targetlocation);
                if (!isResult)
                {
                    _unitOfWorkManage.RollbackTran();
                    return content.Error("新增任务失败");
                }
                return content = await SendWCSTask(taskDTO);
            }
            return content.Error("未找到提升机站点");
        }
        catch (Exception ex)
        {
            return content.Error(ex.Message);
        }
    }
    #endregion
    #region è¯·æ±‚AGV搬运任务
    public async Task<WebResponseContent> RequestAGVCarryTaskAsync(RequestTaskDto taskDto)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            var Sourcelocation = await _locationRepository.QueryFirstAsync(x => x.LocationCode == taskDto.Position);
            DtLocationInfo Targetlocation = await GetAGVEmptyCacheLocation(taskDto.AreaId);
            if (Targetlocation == null || Sourcelocation == null)
            {
                return content.Error("起点未定义或终点区域未找到空闲库位");
            }
            if (!IsSamefloor(Sourcelocation, Targetlocation))
            {
                return content.Error("同楼层不允许请求跨楼层任务");
            }
            Dt_Task taskNew = new Dt_Task
            {
                Grade = 1,
                Roadway = "AGV",
                TargetAddress = Targetlocation.LocationCode,
                Dispatchertime = DateTime.Now,
                MaterialNo = "",
                NextAddress = taskDto.TargetAddress,
                OrderNo = null,
                PalletCode = taskDto.PalletCode,
                SourceAddress = taskDto.Position,
                CurrentAddress = taskDto.Position,
                TaskState = (int)TaskAGVCarryStatusEnum.CarryNew,
                TaskType = (int)TaskAGVCarryTypeEnum.Carry,
                TaskNum = BaseDal.GetTaskNo().Result,
                CreateDate = DateTime.Now,
                TaskId = 0,
                AGVTaskNum = GenerateUniqueId(),
                Floor = Sourcelocation.Floor,
            };
            var taskDTO = CreateListTaskDTO(taskNew);
            var isResult = await AddTaskAsync(taskNew, Sourcelocation, Targetlocation);
            if (!isResult)
            {
                _unitOfWorkManage.RollbackTran();
                return content.Error("新增任务失败");
            }
            return content = await SendWCSTask(taskDTO);
        }
        catch (Exception ex)
        {
            return content.Error(ex.Message);
        }
    }
    public async Task<WebResponseContent> RequestPointAGVCarryTaskAsync(RequestTaskDto taskDto)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            var Sourcelocation = await _locationRepository.QueryFirstAsync(x => x.LocationCode == taskDto.Position);
            var Targetlocation = await _locationRepository.QueryFirstAsync(x => x.LocationCode == taskDto.TargetAddress);
            if (Targetlocation == null || Sourcelocation == null)
            {
                return content.Error("起点或终点未定义");
            }
            if (!IsSamefloor(Sourcelocation, Targetlocation))
            {
                return content.Error("同楼层不允许请求跨楼层任务");
            }
            Dt_Task taskNew = new Dt_Task
            {
                Grade = 1,
                Roadway = "AGV",
                TargetAddress = Targetlocation.LocationCode,
                Dispatchertime = DateTime.Now,
                MaterialNo = "",
                NextAddress = taskDto.TargetAddress,
                OrderNo = null,
                PalletCode = taskDto.PalletCode,
                SourceAddress = taskDto.Position,
                CurrentAddress = taskDto.Position,
                TaskState = (int)TaskAGVCarryStatusEnum.CarryNew,
                TaskType = (int)TaskAGVCarryTypeEnum.Carry,
                TaskNum = BaseDal.GetTaskNo().Result,
                CreateDate = DateTime.Now,
                TaskId = 0,
                AGVTaskNum = GenerateUniqueId(),
                Floor = Sourcelocation.Floor,
            };
            var taskDTO = CreateListTaskDTO(taskNew);
            var isResult = await AddTaskAsync(taskNew, Sourcelocation, Targetlocation);
            if (!isResult)
            {
                _unitOfWorkManage.RollbackTran();
                return content.Error("新增任务失败");
            }
            return content = await SendWCSTask(taskDTO);
        }
        catch (Exception ex)
        {
            return content.Error(ex.Message);
        }
    }
    #endregion
    #region èŽ·å–AGV任务号
    private static readonly Random _random = new Random();
    public static string GenerateUniqueId()
    {
        // èŽ·å–å½“å‰æ¯«ç§’çº§æ—¶é—´æˆ³
        long timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
        // ç”Ÿæˆ4位随机数(0000-9999)
        int randomNumber = _random.Next(0, 10000);
        string randomPart = randomNumber.ToString("D4"); // è¡¥é›¶åˆ°4位
        return $"{timestamp}{randomPart}";
    }
    #endregion
    #endregion å¤–部接口方法
    #region è°ƒç”¨WCS接口
    private string GetAGVIPAddress(string baseIp, string name)
    {
        var configz = _configService.GetConfigsByCategory(CateGoryConst.CONFIG_SYS_IPAddress);
        var wcsBasez = configz.Where(x => x.ConfigKey == baseIp).FirstOrDefault()?.ConfigValue;
        var address = configz.Where(x => x.ConfigKey == name).FirstOrDefault()?.ConfigValue;
        if (wcsBasez == null || address == null)
        {
            throw new InvalidOperationException("WMS IP æœªé…ç½®");
        }
        return wcsBasez + address;
    }
    public async Task<WebResponseContent> SendWCSTask(List<WMSTaskDTO> taskDTO)
    {
        WebResponseContent content = new WebResponseContent();
        var AgvSendTaskAddrss = GetAGVIPAddress(SysConfigConst.WCSIPAddress, SysConfigConst.ReceiveTask);
        // å‘送请求并等待响应
        var result = await HttpHelper.PostAsync(AgvSendTaskAddrss, taskDTO.ToJsonString());
        content = JsonConvert.DeserializeObject<WebResponseContent>(result.ToString());
        return content;
    }
    #endregion
    #region å†…部调用方法
    /// <summary>
    /// åˆ›å»ºä»»åŠ¡DTO
    /// </summary>
    private List<WMSTaskDTO> CreateListTaskDTO(Dt_Task task)
    {
        return new List<WMSTaskDTO> { new WMSTaskDTO
        {
            TaskNum = task.TaskNum.Value,
            Grade = task.Grade.Value,
            PalletCode = task.PalletCode,
            RoadWay = task.Roadway,
            SourceAddress = task.SourceAddress,
            TargetAddress = task.TargetAddress,
            TaskState = task.TaskState,
            Id = 0,
            TaskType = task.TaskType,
            AGVTaskNum = task.AGVTaskNum,
        } };
    }
    private WMSTaskDTO CreateTaskDTO(Dt_Task task)
    {
        return new WMSTaskDTO
        {
            TaskNum = task.TaskNum.Value,
            Grade = task.Grade.Value,
            PalletCode = task.PalletCode,
            RoadWay = task.Roadway,
            SourceAddress = task.SourceAddress,
            TargetAddress = task.TargetAddress,
            TaskState = task.TaskState,
            Id = 0,
            TaskType = task.TaskType,
            AGVTaskNum = task.AGVTaskNum,
        };
    }
    private bool IsAcrossFloor(DtLocationInfo Sourcelocation,DtLocationInfo Targetlocation)
    {
        return Sourcelocation.Floor == Targetlocation.Floor;
    }
    private bool IsSamefloor(DtLocationInfo Sourcelocation, DtLocationInfo Targetlocation)
    {
        return Sourcelocation.Floor == Targetlocation.Floor;
    }
    private async Task DeleteStockInfoAsync(int stockId)
    {
        var isStockUpdated = await _stockInfoRepository.DeleteDataByIdAsync(stockId);
@@ -136,316 +930,6 @@
        }
    }
    #endregion å‡ºåº“任务完成
    #region ç§»åº“任务完成
    /// <summary>
    /// ç§»åº“任务完成
    /// </summary>
    /// <param name="saveModel">任务数据合集</param>
    /// <returns>返回结果集</returns>
    public async Task<WebResponseContent> CompleteTransferTaskAsync(Dt_Task task, DtStockInfo stock)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            // æ›´æ–°è´§ä½å’Œåº“存信息
            (DtStockInfo updateStock, DtLocationInfo locationInForm, DtLocationInfo locationInfoTo) = UpdateStockLocation(stock, task);
            var taskHty = CreateHistoricalTask(task);
            LogFactory.GetLog("任务完成").InfoFormat(true, "移库任务完成", $"货位地址:{task.TargetAddress},修改后库存数据:{JsonConvert.SerializeObject(updateStock)},原先货位数据:{locationInForm}");
            // æ‰§è¡Œæ•°æ®åº“事务
            bool isResult = false;
            if (isResult)
                content.OK("移库任务完成成功");
            else
                content.Error("移库任务完成失败");
        }
        catch (Exception err)
        {
            Console.WriteLine(err.Message.ToString());
        }
        return content;
    }
    #endregion ç§»åº“任务完成
    #region å…¥åº“任务完成
    /// <summary>
    /// å®Œæˆå…¥åº“任务
    /// </summary>
    /// <param name="task">任务数据合集</param>
    /// <returns>返回结果集</returns>
    public async Task<WebResponseContent> CompleteInboundTaskAsync(Dt_Task task)
    {
        // åˆå§‹åŒ–响应内容
        WebResponseContent content = new WebResponseContent();
        try
        {
        }
        catch (Exception ex)
        {
            content.Error(ex.Message);
        }
        return content;
    }
    #endregion å…¥åº“任务完成
    #region ä»»åŠ¡å®Œæˆ
    /// <summary>
    /// å®Œæˆä»»åŠ¡
    /// </summary>
    /// <param name="taskNum">任务编号</param>
    /// <returns>返回结果集</returns>
    public async Task<WebResponseContent> CompleteAsync(int taskNum)
    {
        // åˆå§‹åŒ–响应内容
        WebResponseContent content = new WebResponseContent();
        // æå–任务数据
        LogFactory.GetLog("任务完成").InfoFormat(true, "提取任务数据", $"任务号:{taskNum}");
        // éªŒè¯ä»»åŠ¡æ˜¯å¦å­˜åœ¨
        var task = await GetByTaskNum(taskNum);
        if (task == null)
        {
            return content.Error("任务不存在");
        }
        LogFactory.GetLog("任务完成").InfoFormat(true, "验证任务是否存在", JsonConvert.SerializeObject(task));
        // éªŒè¯åº“存是否存在
        var stock = await _stockInfoRepository.QueryFirstNavAsync(x => x.PalletCode == task.PalletCode);
        // æ ¹æ®ä»»åŠ¡ç±»åž‹è°ƒç”¨ç›¸åº”çš„å®Œæˆä»»åŠ¡æ–¹æ³•
        switch (task.TaskType)
        {
            case (int)TaskInboundTypeEnum.Inbound:
            case (int)TaskInboundTypeEnum.InTray:
            case (int)TaskInboundTypeEnum.InNG:
            case (int)TaskInboundTypeEnum.InQuality:
                LogFactory.GetLog("任务完成").InfoFormat(true, "入库任务", "");
                return await CompleteInboundTaskAsync(task);
            case (int)TaskOutboundTypeEnum.OutTray:
            case (int)TaskOutboundTypeEnum.Outbound:
            case (int)TaskOutboundTypeEnum.OutNG:
                LogFactory.GetLog("任务完成").InfoFormat(true, "出库任务", "");
                return await CompleteOutboundTaskAsync(task, stock);
            case (int)TaskRelocationTypeEnum.Relocation:
                return await CompleteTransferTaskAsync(task, stock);
            default:
                return content.Error("任务类型不存在");
        }
    }
    #endregion ä»»åŠ¡å®Œæˆ
    #region è¯·æ±‚任务入库
    public async Task<WebResponseContent> RequestTaskAsync(RequestTaskDto input)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
        }
        catch (Exception err)
        {
            // æ›´è¯¦ç»†çš„异常处理,可以根据异常类型记录不同的错误日志等
            content.Error(err.Message);
            Console.WriteLine(err.Message);
            LogFactory.GetLog($"请求入库异常").Info(true, $"异常信息【{err.Message}】异常行【{err.StackTrace}】");
        }
        return content;
    }
    /// <summary>
    /// æ›´æ–°ä»»åŠ¡è´§ä½
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<WebResponseContent> UpdateExistingTask(RequestTaskDto input)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            var task = await BaseDal.QueryFirstAsync(x => x.PalletCode == input.PalletCode);
            if (task == null)
                return content.Error($"暂未找到【{input.PalletCode}】的任务");
            return content = await UpdateExistingTask(input, task);
        }
        catch (Exception err)
        {
            return content.Error(err.Message);
        }
    }
    /// <summary>
    /// ç©ºæ‰˜ç›˜å…¥åº“申请
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<WebResponseContent> RequestTrayInTaskAsync(RequestTaskDto input)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            content.OK();
        }
        catch (Exception ex)
        {
            content.Error(ex.Message);
        }
        return content;
    }
    #endregion è¯·æ±‚任务入库
    #region è¯·æ±‚出库(实盘&空盘)
    /// <summary>
    /// è¯·æ±‚托盘任务
    /// </summary>
    /// <param name="position">目标位置</param>
    /// <param name="tag">托盘类型(1:实盘,2:空盘)</param>
    /// <param name="areaCode">区域编码</param>
    /// <param name="roadways">巷道编码集合</param>
    /// <returns>返回结果集</returns>
    public async Task<WebResponseContent> RequestTrayOutTaskAsync(string position, int tag, string areaCode, List<string> areaCodes, string productionLine)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            // è¿”回成功响应
            return content.OK();
        }
        catch (Exception ex)
        {
            // è®°å½•异常信息并抛出
            LogFactory.GetLog("请求托盘任务").Error(true, ex);
            ConsoleHelper.WriteErrorLine("请求空/实托盘任务" + ex.Message + "\r\n" + ex.StackTrace);
            return content.Error(ex.Message);
        }
    }
    /// <summary>
    /// åˆ›å»ºä»»åŠ¡å®žä¾‹
    /// </summary>
    private Dt_Task CreateTask(DtStockInfo stockInfo, string position, int tag)
    {
        return new Dt_Task
        {
            Grade = tag == 104 ? (stockInfo.LocationInfo.RoadwayNo.Contains("CWSC") ? 1 : 2) : (stockInfo.LocationInfo.RoadwayNo.Contains("CWSC") ? 2 : 1),
            Roadway = stockInfo.LocationInfo.RoadwayNo,
            TargetAddress = position,
            Dispatchertime = DateTime.Now,
            MaterialNo = "",
            NextAddress = position,
            OrderNo = null,
            PalletCode = stockInfo.PalletCode,
            SourceAddress = stockInfo.LocationCode,
            CurrentAddress = stockInfo.LocationCode,
            TaskState = (int)TaskOutStatusEnum.OutNew,
            TaskType = tag,
            TaskNum = BaseDal.GetTaskNo().Result,
            Creater = "System", // ä¿®æ­£æ‹¼å†™é”™è¯¯
            CreateDate = DateTime.Now,
            TaskId = 0,
            ProductionLine = stockInfo.ProductionLine,
            ProcessCode = stockInfo.ProcessCode,
        };
    }
    /// <summary>
    /// åˆ›å»ºä»»åŠ¡DTO
    /// </summary>
    private WMSTaskDTO CreateTaskDTO(Dt_Task task)
    {
        return new WMSTaskDTO
        {
            TaskNum = task.TaskNum.Value,
            Grade = task.Grade.Value,
            PalletCode = task.PalletCode,
            RoadWay = task.Roadway,
            SourceAddress = task.SourceAddress,
            TargetAddress = task.TargetAddress,
            TaskState = task.TaskState.Value,
            Id = 0,
            TaskType = task.TaskType,
            ProductionLine = task.ProductionLine,
        };
    }
    #endregion è¯·æ±‚出库(实盘&空盘)
    #region ä»»åŠ¡çŠ¶æ€æ›´æ”¹
    /// <summary>
    /// æ›´æ–°ä»»åŠ¡çŠ¶æ€&出库解盘
    /// </summary>
    /// <param name="taskNum"></param>
    /// <param name="taskState"></param>
    /// <returns></returns>
    public async Task<WebResponseContent> UpdateTaskStatus(int taskNum, int taskState)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            var task = await BaseDal.QueryFirstAsync(x => x.TaskNum == taskNum);
            if (task == null)
                return content.Error("未找到任务");
            if (taskState == (int)TaskOutStatusEnum.Line_OutFinish || taskState == (int)TaskInStatusEnum.SC_InFinish)
            {
                var taskHty = CreateHistoricalTask(task);
                await _unitOfWorkManage.UseTranAsync(async () =>
                {
                    var asb = await BaseDal.DeleteDataByIdAsync(task.TaskId);
                    var asbHty = await _task_HtyRepository.AddDataAsync(taskHty) > 0;
                    if (asb && asbHty)
                        content.OK();
                    else
                        throw new Exception();
                });
                content.OK();
            }
            else
            {
                task.TaskState = taskState;
                var asb = await BaseDal.UpdateDataAsync(task);
                if (asb)
                    content.OK();
                else
                    content.Error();
            }
        }
        catch (Exception ex)
        {
            content.Error(ex.Message);
        }
        return content;
    }
    #endregion ä»»åŠ¡çŠ¶æ€æ›´æ”¹
    #endregion å¤–部接口方法
    #region å†…部调用方法
    public override WebResponseContent DeleteData(object[] key)
    {
        WebResponseContent content = new WebResponseContent();
@@ -482,7 +966,10 @@
    {
        return await BaseDal.QueryFirstAsync(x => x.TaskNum == taskNum);
    }
    public async Task<Dt_Task> GetByTaskAddress(string SourceAddress, string TargetAddress)
    {
        return await BaseDal.QueryFirstAsync(x => x.SourceAddress == SourceAddress|| x.TargetAddress== TargetAddress);
    }
    #endregion å†…部调用方法
    #region private å†…部方法
@@ -537,79 +1024,10 @@
    private static readonly SemaphoreSlim _semaphoreUpdate = new SemaphoreSlim(1, 1);
    // æ›´æ–°ä»»åŠ¡è´§ä½
    private async Task<WebResponseContent> UpdateExistingTask(RequestTaskDto input, Dt_Task task)
    {
        await _semaphoreUpdate.WaitAsync();
        try
        {
            if (task == null)
            {
                return new WebResponseContent().Error("任务对象为空");
            }
            try
            {
                // åˆ›å»ºWebResponseContent对象
                var content = new WebResponseContent();
                var location = await GetEmptyLocation(task.Roadway);
                if (location == null)
                {
                    return content.Error("无法获取货位信息");
                }
                string toAddress = location.LocationCode;
                int taskState = (int)TaskInStatusEnum.Line_InFinish;
                int beforeStatus = location.LocationStatus;
                // æ›´æ–°è´§ä½ä¿¡æ¯
                location.LocationStatus = (int)LocationEnum.Lock;
                // æ›´æ–°ä»»åŠ¡ä¿¡æ¯
                MapTaskProperties(task, input, toAddress, taskState);
                // å¼€å§‹äº‹åŠ¡
                var isResult = await UpdateTaskAsync(task, location, beforeStatus);
                if (!isResult)
                {
                    _unitOfWorkManage.RollbackTran();
                    return content.Error("更新任务失败");
                }
                // æäº¤äº‹åŠ¡
                _unitOfWorkManage.CommitTran();
                return content.OK(data: task);
            }
            catch (Exception ex)
            {
                // å›žæ»šäº‹åŠ¡
                _unitOfWorkManage.RollbackTran();
                // è¿™é‡Œå¯ä»¥æ·»åŠ æ—¥å¿—è®°å½•
                return new WebResponseContent().Error($"更新任务时发生错误: {ex.Message}");
            }
        }
        catch (Exception)
        {
            throw;
        }
        finally { _semaphoreUpdate.Release(); }
    }
    private void MapTaskProperties(Dt_Task task, RequestTaskDto input, string toAddress, int taskState)
    {
        task.CurrentAddress = input.Position;
        task.TargetAddress = toAddress;
        task.NextAddress = toAddress;
        task.TaskState = taskState;
    }
    // ä¿®æ”¹ä»»åŠ¡
    private async Task<bool> UpdateTaskAsync(Dt_Task task, DtLocationInfo location, int beforeStatus)
    {
        bool isResult = await BaseDal.UpdateDataAsync(task);
        bool isTaskDetail = await _taskExecuteDetailRepository.AddDetailAsync(task, false, TaskDescription.GetTaskUpdateDescription(task.PalletCode, task.CurrentAddress, task.TargetAddress, TaskInStatusEnum.Line_InFinish.GetIntegralRuleTypeEnumDesc()));
        LocationChangeRecordDto changeRecordDto = new LocationChangeRecordDto()
        {
            AfterStatus = location.LocationStatus,
@@ -623,92 +1041,72 @@
        bool isUpdateChange = _locationStatusChangeRecordRepository.AddStatusChangeRecord(changeRecordDto);
        bool isUpdateLo = await _locationRepository.UpdateDataAsync(location);
        return isResult && isUpdateLo && isTaskDetail;
        return isResult && isUpdateLo;
    }
    /// <summary>
    /// åˆ›å»ºæ–°ä»»åŠ¡
    /// </summary>
    /// <param name="input">请求模型</param>
    /// <param name="process">巷道</param>
    /// <param name="flag">标识(0-入库,1-空托盘入库,2-NG入库,3-出库)</param>
    /// <returns></returns>
    private async Task<WebResponseContent> CreateNewTask(RequestTaskDto input, string productionLine, string processCode, List<string> process = null, int flag = 0)
    private async Task<bool> AddTaskAsync(Dt_Task task, DtLocationInfo Sourcelocation, DtLocationInfo Targetlocation)
    {
        WebResponseContent content = new WebResponseContent();
        bool isResult = await BaseDal.AddDataAsync(task) > 0;
        int SourcebeforeStatus = Sourcelocation.LocationStatus;
        // èŽ·å–ç›®æ ‡åœ°å€
        //string ToAddress = await GetRoadWayAsync(process);
        string ToAddress = string.Empty;
        if (flag < 2)
            ToAddress = await GetRoadWayAsync(process);
        else
            ToAddress = process[0];
        if (string.IsNullOrEmpty(ToAddress))
        int TargetbeforeStatus = Targetlocation.LocationStatus;
        Sourcelocation.LocationStatus = (int)LocationEnum.InStockDisable;
        Targetlocation.LocationStatus = (int)LocationEnum.Lock;
        List<LocationChangeRecordDto> changeRecordDto = new List<LocationChangeRecordDto>()
        {
            return content.Error("无法获取目标地址");
        }
        // åˆ›å»ºæ–°ä»»åŠ¡å®žä¾‹
        var task = new Dt_Task
        {
            CurrentAddress = input.Position,
            Grade = 1,
            Roadway = ToAddress,
            TargetAddress = ToAddress,
            Dispatchertime = DateTime.Now,
            MaterialNo = "",
            NextAddress = ToAddress,
            OrderNo = null,
            PalletCode = input.PalletCode,
            SourceAddress = input.Position,
            TaskState = flag == 3 ? (int)TaskOutStatusEnum.OutNew : (int)TaskInStatusEnum.InNew,
            TaskType = flag == 0 ? (int)TaskInboundTypeEnum.Inbound : flag == 1 ? (int)TaskInboundTypeEnum.InTray : flag == 2 ? (int)TaskInboundTypeEnum.InNG : (int)TaskOutboundTypeEnum.Outbound,
            TaskNum = await BaseDal.GetTaskNo(),
            Creater = "System",
            ProductionLine = productionLine,
            ProcessCode = processCode
            new LocationChangeRecordDto()
            {
                AfterStatus = Sourcelocation.LocationStatus,
                BeforeStatus = SourcebeforeStatus,
                TaskNum = task.TaskNum.Value,
                LocationId = Sourcelocation.Id,
                LocationCode = Sourcelocation.LocationCode,
                ChangeType = (int)StatusChangeTypeEnum.AutomaticDelivery,
            },
            new LocationChangeRecordDto()
            {
                AfterStatus = Targetlocation.LocationStatus,
                BeforeStatus = TargetbeforeStatus,
                TaskNum = task.TaskNum.Value,
                LocationId = Targetlocation.Id,
                LocationCode = Targetlocation.LocationCode,
                ChangeType = (int)StatusChangeTypeEnum.AutomaticDelivery,
            },
        };
        // å°è¯•添加新任务
        var taskId = await BaseDal.AddDataAsync(task);
        bool isResult = taskId > 0;
        if (isResult)
        {
            task.TaskId = taskId;
            isResult = await _taskExecuteDetailRepository.AddDetailAsync(task, false, TaskDescription.GetTaskUpdateDescription(input.PalletCode, input.Position, ToAddress, TaskInStatusEnum.InNew.GetIntegralRuleTypeEnumDesc()));
        bool isUpdateChange = _locationStatusChangeRecordRepository.AddStatusChangeRecord(changeRecordDto);
        bool Source = await _locationRepository.UpdateDataAsync(Sourcelocation);
        bool Target = await _locationRepository.UpdateDataAsync(Targetlocation);
            //var location = _locationRepository.QueryFirst(x => x.RoadwayNo == task.Roadway && x.LocationCode == task.TargetAddress);
            //location.LocationStatus = (int)LocationEnum.Lock;
            //var isLocation = _locationRepository.UpdateData(location);
            if (isResult)
            {
                // åˆ›å»ºWMS任务
                WMSTaskDTO taskDTO = new WMSTaskDTO()
                {
                    TaskNum = task.TaskNum.Value,
                    Grade = 1,
                    PalletCode = task.PalletCode,
                    RoadWay = task.Roadway,
                    SourceAddress = task.SourceAddress,
                    TargetAddress = task.TargetAddress,
                    TaskState = task.TaskState.Value,
                    Id = 0,
                    TaskType = task.TaskType,
                    ProductionLine = task.ProductionLine
                };
                content.OK(data: taskDTO);
            }
            else
                content.Error("添加任务失败");
        }
        else
            content.Error("添加任务失败");
        return content;
        return isResult && Source && Target;
    }
    private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
    private static List<LocationCache> locationCaches = new List<LocationCache>();
    private async Task<bool> AddInBoundTaskAsync(Dt_Task task, DtLocationInfo location)
    {
        bool isResult = await BaseDal.AddDataAsync(task) > 0;
        int beforeStatus = location.LocationStatus;
        location.LocationStatus = (int)LocationEnum.InStockDisable;
        LocationChangeRecordDto changeRecordDto = new LocationChangeRecordDto()
        {
            AfterStatus = location.LocationStatus,
            BeforeStatus = beforeStatus,
            TaskNum = task.TaskNum.Value,
            LocationId = location.Id,
            LocationCode = location.LocationCode,
            ChangeType = (int)StatusChangeTypeEnum.AutomaticStorage,
        };
        bool isUpdateChange = _locationStatusChangeRecordRepository.AddStatusChangeRecord(changeRecordDto);
        bool loc = await _locationRepository.UpdateDataAsync(location);
        return isResult && loc;
    }
    /// <summary>
    /// èŽ·å–è´§ä½å·
@@ -716,83 +1114,110 @@
    /// <returns></returns>
    public async Task<DtLocationInfo> GetEmptyLocation(string roadWay)
    {
        await _semaphore.WaitAsync();
        try
        {
            List<LocationCache> removeItems = locationCaches.Where(x => (DateTime.Now - x.DateTime).TotalMinutes > 5).ToList();//查询添加静态变量超过5分钟的货位
            int count = removeItems.Count;
            for (int i = 0; i < count; i++)
            List<DtLocationInfo> locations = await _locationRepository.QueryDataAsync(x => x.RoadwayNo == "SC1" && x.LocationStatus == 0 && x.EnalbeStatus == 1);
            if (locations.Where(x => x.Row == 2).ToList().OrderBy(x => x.Layer).ThenBy(x => x.Column).FirstOrDefault() != null)
            {
                locationCaches.Remove(removeItems[i]);//移除查询添加静态变量超过5分钟的货位
                return locations.Where(x => x.Row == 2).ToList().OrderBy(x => x.Layer).ThenBy(x => x.Column).FirstOrDefault();
            }
            List<string> lockLocations = locationCaches.Select(x => x.LocationCode).ToList();
            List<DtLocationInfo> LocationInfoList = await _locationRepository.QueryDataAsync(x => x.RoadwayNo == roadWay && x.LocationStatus == (int)LocationEnum.Free && x.EnalbeStatus == EnableEnum.Enable.ObjToInt());
            List<DtLocationInfo> LocationInfoResult = new List<DtLocationInfo>();
            foreach (DtLocationInfo item in LocationInfoList)
            else if (locations.Where(x => x.Row == 3).ToList().OrderBy(x => x.Layer).ThenBy(x => x.Column).FirstOrDefault() != null)
            {
                DtLocationInfo locationItem = new DtLocationInfo();
                if (item.Depth == 2)
                {
                    locationItem = _locationRepository.QueryFirst(x => x.Column == item.Column && x.RoadwayNo == item.RoadwayNo && x.Layer == item.Layer && x.Depth != item.Depth && x.Row != item.Row && (SqlFunc.Abs(x.Row - item.Row) == 1) && x.LocationStatus == (int)LocationEnum.Free && x.EnalbeStatus == EnableEnum.Enable.ObjToInt());
                    if (locationItem != null)
                    {
                        LocationInfoResult.Add(item);
                    }
                }
                else
                {
                    locationItem = _locationRepository.QueryFirst(x => x.Column == item.Column && x.RoadwayNo == item.RoadwayNo && x.Layer == item.Layer && x.Depth != item.Depth && x.Row != item.Row && (SqlFunc.Abs(x.Row - item.Row) == 1) && x.LocationStatus == (int)LocationEnum.InStock && x.EnalbeStatus == EnableEnum.Enable.ObjToInt());
                    if (locationItem != null)
                    {
                        LocationInfoResult.Add(item);
                    }
                }
                return locations.Where(x => x.Row == 3).ToList().OrderBy(x => x.Layer).ThenBy(x => x.Column).FirstOrDefault();
            }
            if (LocationInfoResult.Count < 2)
            else
            {
                throw new Exception("当前空闲货位不足!");
                return locations.Where(x => x.Row == 1).ToList().OrderBy(x => x.Layer).ThenBy(x => x.Column).FirstOrDefault();
            }
            return LocationInfoResult.Where(x => !lockLocations.Contains(x.LocationCode)).OrderByDescending(x => x.Depth).ThenBy(x => x.Column).ThenBy(x => x.Layer).FirstOrDefault();
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
        finally
    }
    public async Task<DtLocationInfo> GetAGVEmptyCacheLocation(int AreaId)
    {
        try
        {
            _semaphore.Release();
            DtLocationInfo location = null;
            switch (AreaId)
            {
                case 2:
                    location = await FromShallowToDeep(AreaId);
                    break;
                    case 3:
                    location = await AGVLIKU(AreaId);
                    break;
                case 5:
                case 6:
                    location = await FromDeepToShallow(AreaId);
                    break;
                default:
                    break;
            }
            return location;
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message) ;
        }
    }
    /// <summary>
    /// æ ¹æ®å··é“获取巷道或站台
    /// ç”±æ·±åˆ°æµ…
    /// </summary>
    /// <param name="AreaId"></param>
    /// <returns></returns>
    public async Task<string> GetRoadWayAsync(List<string> process)
    public async Task<DtLocationInfo> FromDeepToShallow(int AreaId)
    {
        var deviceCode = await SqlSugarHelper.DbWCS.Queryable<Dt_DeviceInfo>()
             .Where(x => x.DeviceStatus == 1.ToString() && process.Contains(x.DeviceCode))
             .Select(x => x.DeviceCode).ToListAsync();
        var minGroup = _locationRepository.QueryData(x => deviceCode.Contains(x.RoadwayNo) && x.LocationStatus == (int)LocationEnum.Free)
             .GroupBy(x => x.RoadwayNo)
             .OrderByDescending(g => g.Count()) // æ ¹æ®æ¯ä¸ªç»„的元素数量排序
             .ToList(); // å–出数量最多的组
        Dictionary<string, int> result = new Dictionary<string, int>();
        foreach (var item in minGroup)
        try
        {
            var number = BaseDal.QueryData(x => x.TargetAddress == item.Key && x.TaskType.GetTaskTypeGroup() == TaskTypeGroup.InboundGroup).Count();
            result.Add(item.Key, item.Count() - number);
            List<DtLocationInfo> locations = await _locationRepository.QueryDataAsync(x => x.AreaId == AreaId && x.LocationStatus == 0 && x.EnalbeStatus == 1);
            var location = locations.OrderByDescending(x => x.Column).ThenBy(x => x.Row).FirstOrDefault();
            return location;
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
    }
        string minRoadwayNo = result.OrderByDescending(x => x.Value).FirstOrDefault().Key; // æ•°é‡æœ€å¤šçš„组的Key
        return minRoadwayNo;
    /// <summary>
    /// ç”±æµ…到深
    /// </summary>
    /// <param name="AreaId"></param>
    /// <returns></returns>
    public async Task<DtLocationInfo> FromShallowToDeep(int AreaId)
    {
        try
        {
            List<DtLocationInfo> locations = await _locationRepository.QueryDataAsync(x => x.AreaId == AreaId && x.LocationStatus == 0 && x.EnalbeStatus == 1);
            var location = locations.OrderBy(x => x.Column).ThenBy(x => x.Row).FirstOrDefault();
            return location;
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
    }
    public async Task<DtLocationInfo> AGVLIKU(int AreaId)
    {
        WebResponseContent content = new WebResponseContent();
        try
        {
            List<DtLocationInfo> locations = await _locationRepository.QueryDataAsync(x => x.AreaId == AreaId && x.LocationStatus == 0 && x.EnalbeStatus == 1);
            var location = locations.OrderBy(x => x.Layer).ThenBy(x => x.Column).FirstOrDefault();
            return location;
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
    }
    #endregion ä»»åŠ¡è¯·æ±‚æ–¹æ³•