1
xiazhengtongxue
2026-03-27 5d55a31d8ce95e511ffb408f38ed06e81742b67e
ÏîÄ¿´úÂë/WCSServices/WIDESEAWCS_TaskInfoService/TaskService.cs
@@ -18,16 +18,25 @@
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using RYB_PTL_API;
using SqlSugar;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.DirectoryServices.Protocols;
using System.Linq;
using System.Net.Http.Headers;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_DTO.Agv;
using WIDESEA_External.Model;
using WIDESEAWCS_BasicInfoService;
using WIDESEAWCS_Common;
using WIDESEAWCS_Common.APIEnum;
using WIDESEAWCS_Common.Helper;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseRepository;
@@ -63,6 +72,8 @@
        private readonly IApiInfoRepository _apiInfoRepository;
        private readonly ILocationInfoRepository _locationInfoRepository;
        private readonly ILocationInfoService _locationInfoService;
        private readonly ILocationStatusChangeRecordService _locationStatusChangeRecordService;
        private readonly IErrorInfoRepository _errorInfoRepository;
        private Dictionary<string, OrderByType> _taskOrderBy = new()
            {
@@ -80,7 +91,7 @@
        public List<int> TaskRelocationTypes => typeof(TaskTypeEnum).GetEnumIndexList().Where(x => x >= 900 && x < 1000).ToList();
        public TaskService(ITaskRepository BaseDal, IMapper mapper, ICacheService cacheService, IRouterService routerService, ITaskExecuteDetailService taskExecuteDetailService, ITaskExecuteDetailRepository taskExecuteDetailRepository, IStationMangerRepository stationMangerRepository, IRouterRepository routerRepository, IApiInfoRepository apiInfoRepository,ILocationInfoRepository locationInfoRepository,IUnitOfWorkManage unitOfWorkManage, ILocationInfoService locationInfoService) : base(BaseDal)
        public TaskService(ITaskRepository BaseDal, IMapper mapper, ICacheService cacheService, IRouterService routerService, ITaskExecuteDetailService taskExecuteDetailService, ITaskExecuteDetailRepository taskExecuteDetailRepository, IStationMangerRepository stationMangerRepository, IRouterRepository routerRepository, IApiInfoRepository apiInfoRepository, ILocationInfoRepository locationInfoRepository, IUnitOfWorkManage unitOfWorkManage, ILocationInfoService locationInfoService, ILocationStatusChangeRecordService locationStatusChangeRecordService, IErrorInfoRepository errorInfoRepository) : base(BaseDal)
        {
            _mapper = mapper;
            _cacheService = cacheService;
@@ -93,6 +104,8 @@
            _locationInfoRepository = locationInfoRepository;
            _unitOfWorkManage = unitOfWorkManage;
            _locationInfoService = locationInfoService;
            _locationStatusChangeRecordService = locationStatusChangeRecordService;
            _errorInfoRepository = errorInfoRepository;
        }
        static object lock_taskReceive = new object();
        /// <summary>
@@ -100,66 +113,77 @@
        /// </summary>
        /// <param name="taskDTOs">WMS任务对象集合</param>
        /// <returns>返回处理结果</returns>
        public WebResponseContent ReceiveWMSTask([NotNull] WMSTaskDTO taskDTO)
        public WMSReceiveTaskContent ReceiveWMSTask([NotNull] WMSTaskDTO taskDTO)
        {
            WebResponseContent content = new WebResponseContent();
            WMSReceiveTaskContent content = new WMSReceiveTaskContent();
            string errorMsg = "";
            try
            {
                lock (lock_taskReceive)
                {
                    WriteLog.Write_Log("入库任务下发", "WMS入库任务接收参数", "接收参数", $"参数:{taskDTO.ToJson()}");
                    List<Dt_Task> tasks = new List<Dt_Task>();
                    Dt_Task taskOld = BaseDal.QueryFirst(x=> taskDTO.Tasks.Select(x => x.TaskDescribe.ContainerCode).Contains(x.PalletCode));
                    if (taskOld != null) throw new Exception($"料箱{taskOld.PalletCode}"+(taskOld.TaskType == TaskTypeEnum.Inbound.ObjToInt() ? "入库任务已存在" : "出库任务已存在"));
                    List<Dt_LocationInfo> locationInfos = _locationInfoRepository.GetCanOut(taskDTO.Tasks.Select(x=>x.TaskDescribe.ContainerCode).ToList());
                    Dt_LocationInfo? noOutLocation = locationInfos.FirstOrDefault(x=>x.LocationStatus != LocationStatusEnum.InStock.ObjToInt() || x.EnableStatus != EnableStatusEnum.Normal.ObjToInt());
                    if (noOutLocation != null) throw new Exception($"料箱{noOutLocation.PalletCode}货位{noOutLocation.LocationCode}状态不可出库");
                    List<Dt_Task> taskOlds = BaseDal.QueryData(x => taskDTO.Tasks.Select(x => x.TaskDescribe.ContainerCode).Contains(x.PalletCode));
                    List<Dt_LocationInfo> locationInfos = _locationInfoRepository.GetCanOut(taskDTO.Tasks.Select(x => x.TaskDescribe.ContainerCode).ToList());
                    List<Dt_StationManger> stationMangers = _stationMangerRepository.QueryData();
                    //下发任务组
                    string taskGroup= taskDTO.TaskGroupCode.IsNullOrEmpty() ? Guid.NewGuid().ToString().Replace("-","") : taskDTO.TaskGroupCode;
                    foreach (var item in taskDTO.Tasks.OrderBy(x=>x.TaskDescribe.ToStationCode))
                    ////下发任务组
                    //string taskGroup= taskDTO.TaskGroupCode.IsNullOrEmpty() ? Guid.NewGuid().ToString().Replace("-","") : taskDTO.TaskGroupCode;
                    foreach (var item in taskDTO.Tasks.OrderBy(x => x.TaskDescribe.ToStationCode))
                    {
                        if (item.TaskDescribe.ToStationCode.IsNullOrEmpty()) throw new Exception($"任务{item.TaskCode}出库目标操作台不能为空");
                        //获取操作台
                        Dt_StationManger? stationManger = stationMangers.FirstOrDefault(x => x.PickStationCode == item.TaskDescribe.ToStationCode);
                        if (stationManger == null) throw new Exception($"任务{item.TaskCode}出库目标操作台{item.TaskDescribe.ToStationCode}不存在");
                        Dt_Task? taskOld = taskOlds.FirstOrDefault(x => x.PalletCode == item.TaskDescribe.ContainerCode);
                        if (taskOld != null)
                        {
                            errorMsg += $"料箱{taskOld.PalletCode}" + (taskOld.TaskType == TaskTypeEnum.Inbound.ObjToInt() ? "入库任务已存在;" : "出库任务已存在;");
                            content.FailData.Add(new BinCodeObj() { Bincode = item.TaskDescribe.ContainerCode });
                            continue;
                        }
                        Dt_LocationInfo? locationInfo = locationInfos.FirstOrDefault(x => x.PalletCode == item.TaskDescribe.ContainerCode);
                        if (locationInfo == null)
                        {
                            errorMsg += $"料箱{item.TaskDescribe.ContainerCode}不存在;";
                            content.FailData.Add(new BinCodeObj() { Bincode = item.TaskDescribe.ContainerCode });
                            continue;
                        };
                        }
                        Dt_LocationInfo? noOutLocation = locationInfos.FirstOrDefault(x => (x.LocationStatus != LocationStatusEnum.InStock.ObjToInt() || x.EnableStatus != EnableStatusEnum.Normal.ObjToInt()) && x.PalletCode == item.TaskDescribe.ContainerCode);
                        if (noOutLocation != null)
                        {
                            errorMsg += $"料箱{noOutLocation.PalletCode}货位{noOutLocation.LocationCode}状态不可出库";
                            content.FailData.Add(new BinCodeObj() { Bincode = noOutLocation.PalletCode });
                            continue;
                        }
                        Dt_Task task = _mapper.Map<Dt_Task>(item);
                        task.SourceAddress = locationInfo.LocationCode;
                        task.CurrentAddress = locationInfo.LocationCode;
                        task.NextAddress = stationManger.PickStationCode;
                        task.TargetAddress = stationManger.PickStationCode;
                        task.GroupId = taskGroup;
                        //task.GroupId = taskGroup;
                        task.TaskType = TaskTypeEnum.Outbound.ObjToInt();
                        task.Roadway = locationInfo.RoadwayNo;
                        task.DeviceCode = stationManger.CraneCode;
                        task.TaskState = TaskStatusEnum.AGV_Execute.ObjToInt();
                        tasks.Add(task);
                        content.SucessData.Add(new BinCodeObj() { Bincode = item.TaskDescribe.ContainerCode });
                    }
                    locationInfos.ForEach(x =>
                    {
                        x.LocationStatus=LocationStatusEnum.Lock.ObjToInt();
                        x.LocationStatus = LocationStatusEnum.Lock.ObjToInt();
                    });
                    //添加任务更新货位数据
                    _unitOfWorkManage.BeginTran();
                    BaseDal.AddData(tasks);
                    _locationInfoRepository.UpdateData(locationInfos);
                    _unitOfWorkManage.CommitTran();
                    _taskExecuteDetailService.AddTaskExecuteDetail(tasks.Select(x => x.TaskNum).ToList(), "接收WMS任务");
                    content = tasks.Count > 0 ? content.OK("成功!"+(errorMsg.IsNullOrEmpty()? "": errorMsg)) : content.Error("失败");
                    if (tasks.Count > 0)
                    {
                        _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfos, LocationStatusEnum.InStock, LocationStatusEnum.Lock, LocationChangeType.OutboundAssignLocation, tasks);
                    }
                    content.OK(errorMsg.IsNullOrEmpty() ? "成功" : errorMsg);
                }
            }
            catch (Exception ex)
@@ -168,46 +192,272 @@
            }
            return content;
        }
        static object lock_containerFlow = new object();
        /// <summary>
        /// å®¹å™¨å…¥åº“创建任务
        /// </summary>
        /// <returns></returns>
        public WebResponseContent ContainerFlow(ContainerFlowDTO containerFlowDTO, string deviceCode)
        public WebResponseContent ContainerFlow(ContainerFlowDTO containerFlowDTO, string deviceCode, string stationCode, int type = 0)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                lock (lock_containerFlow)
                List<Dt_LocationInfo> locationInfos = _locationInfoRepository.QueryData();
                Dt_LocationInfo? locationInfo = locationInfos.FirstOrDefault(x => x.PalletCode == containerFlowDTO.ContainerCode);
                if (locationInfo != null) throw new Exception($"库位料箱号{containerFlowDTO.ContainerCode}已存在");
                Dt_Task taskOld = BaseDal.QueryFirst(x => x.PalletCode == containerFlowDTO.ContainerCode);
                if (taskOld != null && taskOld.PalletCode == containerFlowDTO.ContainerCode && taskOld.TaskType == TaskTypeEnum.Inbound.ObjToInt() && taskOld.TaskState == TaskStatusEnum.CL_Executing.ObjToInt() && taskOld.DeviceCode == deviceCode)
                {
                    List<Dt_LocationInfo> locationInfos = _locationInfoRepository.QueryData();
                    Dt_LocationInfo? locationInfo = locationInfos.FirstOrDefault(x=>x.PalletCode== containerFlowDTO.ContainerCode);
                    if (locationInfo != null) throw new Exception($"库位料箱号{containerFlowDTO.ContainerCode}已存在");
                    if (BaseDal.QueryFirst(x=>x.PalletCode==containerFlowDTO.ContainerCode)!=null) throw new Exception($"料箱号{containerFlowDTO.ContainerCode}任务已存在");
                    Dt_LocationInfo? noInLocation = locationInfos.FirstOrDefault(x => x.LocationStatus == LocationStatusEnum.Free.ObjToInt() && x.EnableStatus == EnableStatusEnum.Normal.ObjToInt());
                    if (noInLocation == null) throw new Exception($"可用货位不足!");
                    Dt_StationManger stationManger = _stationMangerRepository.QueryFirst(x => x.StationType == StationTypeEnum.StationType_OnlyInbound.ObjToInt() && x.StationDeviceCode == deviceCode);
                    //创建任务
                    Dt_Task task = new Dt_Task();
                    task.PalletCode = containerFlowDTO.ContainerCode;
                    task.SourceAddress = containerFlowDTO.SlotCode;
                    task.CurrentAddress = containerFlowDTO.SlotCode;
                    task.NextAddress = stationManger.StationCode;
                    task.TargetAddress = "";
                    task.WMSId = "";
                    task.TaskType = TaskTypeEnum.Inbound.ObjToInt();
                    task.Roadway = noInLocation.RoadwayNo;
                    task.DeviceCode = stationManger.StationDeviceCode;
                    task.TaskState = TaskStatusEnum.CL_Executing.ObjToInt();
                    //添加任务
                    BaseDal.AddData(task);
                    _taskExecuteDetailService.AddTaskExecuteDetail(new List<int>() { task.TaskNum }, "创建入库任务");
                    content.OK("成功");
                    //Thread.Sleep(500);
                    return content.OK();
                }
                if (taskOld != null && taskOld.PalletCode == containerFlowDTO.ContainerCode && taskOld.TaskType == TaskTypeEnum.Inbound.ObjToInt() && taskOld.TaskState == TaskStatusEnum.CL_Executing.ObjToInt() && taskOld.DeviceCode != deviceCode)
                {
                    Dt_StationManger stationOld = _stationMangerRepository.QueryFirst(x => x.StationType == StationTypeEnum.StationType_OnlyInbound.ObjToInt() && x.StationDeviceCode == deviceCode);
                    string oldSlotCode = taskOld.SourceAddress;
                    taskOld.SourceAddress = containerFlowDTO.SlotCode;
                    taskOld.CurrentAddress = containerFlowDTO.SlotCode;
                    taskOld.NextAddress = stationOld.StationCode;
                    taskOld.DeviceCode = stationOld.StationDeviceCode;
                    //更新任务
                    BaseDal.UpdateData(taskOld);
                    _taskExecuteDetailService.AddTaskExecuteDetail(new List<int>() { taskOld.TaskNum }, $"{oldSlotCode}换至{containerFlowDTO.SlotCode}入库");
                    return content.OK();
                }
                else if (taskOld != null)
                {
                    throw new Exception($"料箱号{containerFlowDTO.ContainerCode}" + (taskOld.TaskType == TaskTypeEnum.Inbound.ObjToInt() ? "入库AGV执行中" : "出库AGV执行中"));
                }
                Dt_LocationInfo? noInLocation = locationInfos.FirstOrDefault(x => x.LocationStatus == LocationStatusEnum.Free.ObjToInt() && x.EnableStatus == EnableStatusEnum.Normal.ObjToInt());
                if (noInLocation == null) throw new Exception($"可用货位不足!");
                Dt_StationManger stationManger = _stationMangerRepository.QueryFirst(x => x.StationType == StationTypeEnum.StationType_OnlyInbound.ObjToInt() && x.StationDeviceCode == deviceCode);
                //创建任务
                Dt_Task task = new Dt_Task();
                task.PalletCode = containerFlowDTO.ContainerCode;
                task.SourceAddress = containerFlowDTO.SlotCode;
                task.CurrentAddress = containerFlowDTO.SlotCode;
                task.NextAddress = stationManger.StationCode;
                task.TargetAddress = "";
                task.WMSId = "";
                task.TaskType = TaskTypeEnum.Inbound.ObjToInt();
                task.Roadway = noInLocation.RoadwayNo;
                task.DeviceCode = stationManger.StationDeviceCode;
                task.TaskState = TaskStatusEnum.CL_Executing.ObjToInt();
                //添加任务
                int taskId = BaseDal.AddData(task);
                if (type > 0)
                {
                    _taskExecuteDetailService.AddTaskExecuteDetail(new List<int>() { task.TaskNum }, "手动按钮入库");
                }
                else
                {
                    _taskExecuteDetailService.AddTaskExecuteDetail(new List<int>() { task.TaskNum }, "创建入库任务");
                }
                WriteLog.Write_Log("入库任务下发", "容器入库任务添加任务", "添加任务", $"任务:{task.ToJson()}");
                content.OK("成功");
            }
            catch (Exception ex)
            {
                content.Error($"错误信息:{ex.Message}");
            }
            return content;
        }
        /// <summary>
        /// æ’­ç§å¢™åˆå§‹åŒ–
        /// </summary>
        /// <returns></returns>
        public WebResponseContent InitLight()
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                EPLightContent lightContent = INITIALIZATION();
                if (lightContent.Result != "0") throw new Exception($"{lightContent.Msg}");
                content.OK();
            }
            catch (Exception ex)
            {
                content.Error(ex.Message);
            }
            return content;
        }
        /// <summary>
        /// ç»“束作业
        /// </summary>
        /// <returns></returns>
        public WebResponseContent EndLight()
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                EPLightContent lightContent = ENDWORK();
                if (lightContent.Result != "0") throw new Exception($"{lightContent.Msg}");
                content.OK();
            }
            catch (Exception ex)
            {
                content.Error(ex.Message);
            }
            return content;
        }
        /// <summary>
        /// ä¸€æœŸæ’­ç§å¢™ä¸‹å‘
        /// </summary>
        /// <returns></returns>
        public EPLightContent Phase1PickOrderInfoRequest(List<EPLightSendDTO> lightSendDTOs)
        {
            EPLightContent content = new EPLightContent();
            try
            {
                string? url = _apiInfoRepository.QueryFirst(x => x.ApiCode == APIEnum.Phase1PickOrderInfoRequest.ToString())?.ApiAddress;
                if (string.IsNullOrEmpty(url))
                {
                    return content.Error("未找到播种墙下发接口,请检查接口配置");
                }
                bool allSuccess = true;
                StringBuilder errorMessages = new StringBuilder();
                foreach (EPLightSendDTO lightSendDTO in lightSendDTOs)
                {
                    try
                    {
                        bool operationResult;
                        // å¤„理灯光类型转换
                        if (!int.TryParse(lightSendDTO.LIGHTTYPE, out int lightType))
                        {
                            allSuccess = false;
                            errorMessages.AppendLine($"位置 {lightSendDTO.LOCATION} é”™è¯¯: æ— æ•ˆçš„灯光类型 '{lightSendDTO.LIGHTTYPE}'");
                            continue;
                        }
                        // å¤„理关闭灯光请求
                        if (lightType == 2)
                        {
                            operationResult = RYB_PTL.RYB_PTL_CloseDigit5(url, lightSendDTO.LOCATION);
                            // TODO: å…³é—­ç¯å…‰å›žè°ƒå¤„理
                            //List<EPLightBackDTO> lightBackDTOs = new List<EPLightBackDTO>();
                            //List<TaskBackLight> taskBackLights = lightSendDTOs.Select(x => new TaskBackLight()
                            //{
                            //    TagNo = "B1",
                            //    TagCode = x.LOCATION,
                            //}).ToList();
                            //content = WMSLightBack(taskBackLights);
                        }
                        // å¤„理显示灯光请求
                        else
                        {
                            // å¤„理灯光颜色转换
                            if (!int.TryParse(lightSendDTO.LIGHTCOLOR, out int lightColor))
                            {
                                allSuccess = false;
                                errorMessages.AppendLine($"位置 {lightSendDTO.LOCATION} é”™è¯¯: æ— æ•ˆçš„灯光颜色 '{lightSendDTO.LIGHTCOLOR}'");
                                continue;
                            }
                            operationResult = RYB_PTL.RYB_PTL_DspDigit5(
                                url,
                                lightSendDTO.LOCATION,
                                lightSendDTO.QUANTITY,
                                lightType,
                                lightColor);
                        }
                        if (!operationResult)
                        {
                            allSuccess = false;
                            errorMessages.AppendLine($"位置 {lightSendDTO.LOCATION} æ“ä½œå¤±è´¥");
                        }
                    }
                    catch (Exception ex)
                    {
                        allSuccess = false;
                        errorMessages.AppendLine($"位置 {lightSendDTO.LOCATION} å¤„理异常: {ex.Message}");
                    }
                }
                return allSuccess
                    ? content.OK("所有播种墙下发操作成功")
                    : content.Error(errorMessages.ToString());
            }
            catch (Exception ex)
            {
                content.Error(ex.Message);
            }
            return content;
        }
        /// <summary>
        /// æ’­ç§å¢™äº®ç¯
        /// </summary>
        /// <returns></returns>
        public WebResponseContent SendLight(TaskSendLight taskSendLight)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                if (taskSendLight.TagNo == "B1")
                {
                    List<EPLightSendDTO> lightSendDTOs = new List<EPLightSendDTO>()
                    {
                        new EPLightSendDTO
                        {
                            DOCNO = taskSendLight.DocNo,
                            TASKNO= taskSendLight.TaskNo,
                            LOCATION=taskSendLight.TagCode,
                            QUANTITY=taskSendLight.TagQunity,
                            LIGHTCOLOR=taskSendLight.Color switch
                            {
                                "Blue" => "4",
                                "Green" => "2",
                                "Red" => "1",
                                _ => throw new Exception($"未找到颜色定义")
                            },
                            ORDERTYPE="1",
                            LIGHTTYPE=taskSendLight.Mode.ToString(),
                        }
                    };
                    EPLightContent pLightContent = Phase1PickOrderInfoRequest(lightSendDTOs);
                    if (pLightContent.Result != "0") throw new Exception($"{pLightContent.Msg}");
                    content.OK();
                }
                else if (taskSendLight.TagNo == "B2")
                {
                    List<EPLightSendDTO> lightSendDTOs = new List<EPLightSendDTO>()
                    {
                        new EPLightSendDTO
                        {
                            DOCNO = taskSendLight.DocNo,
                            TASKNO= taskSendLight.TaskNo,
                            LOCATION=taskSendLight.TagCode,
                            QUANTITY=taskSendLight.TagQunity,
                            LIGHTCOLOR=taskSendLight.Color switch
                            {
                                "Blue" => "1",
                                "Green" => "2",
                                "Red" => "4",
                                _ => throw new Exception($"未找到颜色定义")
                            },
                            ORDERTYPE="1",
                            LIGHTTYPE=taskSendLight.Mode.ToString(),
                        }
                    };
                    EPLightContent pLightContent = PickOrderInfoRequest(lightSendDTOs);
                    if (pLightContent.Result != "0") throw new Exception($"{pLightContent.Msg}");
                    content.OK();
                }
                else
                {
                    content.OK();
                }
            }
            catch (Exception ex)
            {
                content.Error(ex.Message);
            }
            return content;
        }
@@ -216,14 +466,14 @@
        /// ç”³è¯·å…¥åº“
        /// </summary>
        /// <returns></returns>
        public WebResponseContent RequestInTask(string stationCode,string barCode)
        public WebResponseContent RequestInTask(string stationCode, string barCode)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                lock (lock_requestInTask)
                {
                    Dt_Task task = BaseDal.QueryFirst(x => x.PalletCode == barCode && x.NextAddress == stationCode && x.TaskState == TaskStatusEnum.CL_Executing.ObjToInt());
                    Dt_Task task = BaseDal.QueryFirst(x => x.PalletCode == barCode && x.TaskType == TaskTypeEnum.Inbound.ObjToInt() && x.NextAddress == stationCode && x.TaskState == TaskStatusEnum.CL_Executing.ObjToInt());
                    if (task == null) throw new Exception($"{barCode}料箱未找到任务!");
                    Dt_LocationInfo? locationInfo = _locationInfoService.AssignLocation();
                    if (locationInfo == null) throw new Exception($"可用货位不足!");
@@ -239,7 +489,8 @@
                    _locationInfoRepository.UpdateData(locationInfo);
                    _unitOfWorkManage.CommitTran();
                    _taskExecuteDetailService.AddTaskExecuteDetail(new List<int>() { task.TaskNum }, $"分配货位{locationInfo.LocationCode}");
                    _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, LocationStatusEnum.Free, LocationStatusEnum.Lock, LocationChangeType.InboundAssignLocation, task.TaskNum);
                    WriteLog.Write_Log("入库任务下发", "申请入库接口", "更新任务", $"任务:{task.ToJson()}");
                    content.OK("成功");
                }
            }
@@ -295,7 +546,7 @@
                BaseDal.UpdateData(task);
                _taskExecuteDetailService.AddTaskExecuteDetail(task, task.ExceptionMessage);
                WriteLog.Write_Log("更新任务异常信息", "更新任务接口", "更新任务", $"任务:{task.ToJson()}");
                content = WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
@@ -388,7 +639,7 @@
            return content;
        }
        /// <summary>
        /// æŽ¥å—WMS手动完成任务
        /// </summary>
@@ -398,6 +649,7 @@
        {
            try
            {
                WriteLog.Write_Log("接受WMS手动完成任务", "接受WMS手动完成任务接口", "任务号", $"任务号:{taskNum}");
                Dt_Task task = BaseDal.QueryFirst(x => x.TaskNum == taskNum);
                if (task != null)
                {
@@ -417,9 +669,10 @@
        /// <returns></returns>
        public WebResponseContent AgvTaskFlow(string code)
        {
            WebResponseContent content=new WebResponseContent();
            WebResponseContent content = new WebResponseContent();
            try
            {
                WriteLog.Write_Log("AGV任务放行", "AGV任务放行接口", "料箱号", $"料箱:{code}");
                string? url = _apiInfoRepository.QueryFirst(x => x.ApiCode == APIEnum.AgvTaskFlow.ToString())?.ApiAddress;
                if (string.IsNullOrEmpty(url)) throw new Exception($"{code},未找到AGV任务放行接口,请检查接口配置");
                AgvTaskFlowDTO agvTaskFlowDTO = new AgvTaskFlowDTO()
@@ -429,6 +682,7 @@
                };
                string request = JsonConvert.SerializeObject(agvTaskFlowDTO, settings);
                string response = HttpHelper.Post(url, request);
                WriteLog.Write_Log("AGV任务放行接口请求AGV", "AGV任务放行接口", $"请求:{request},回传:{response}");
                AgvResponseContent agvResponse = JsonConvert.DeserializeObject<AgvResponseContent>(response) ?? throw new Exception($"{code},未接收到AGV任务放行返回值");
                if (!agvResponse.Success) throw new Exception($"料箱{code},AGV任务放行错误,信息:{agvResponse.Message}");
                content.OK();
@@ -443,11 +697,12 @@
        /// WMS料箱到达拣选位上报
        /// </summary>
        /// <returns></returns>
        public WebResponseContent WMSPickUp(string stationCode,string pickCode)
        public WebResponseContent WMSPickUp(string stationCode, string pickCode)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                WriteLog.Write_Log("WMS料箱到达拣选位上报", "WMS料箱到达拣选位上报成接口", "信息", $"拣选位:{stationCode},料箱:{pickCode}");
                string? url = _apiInfoRepository.QueryFirst(x => x.ApiCode == APIEnum.WMSPickArrivedUp.ToString())?.ApiAddress;
                if (string.IsNullOrEmpty(url)) throw new Exception($"未找到WMS料箱到达拣选位上报接口,请检查接口配置");
                ContainerArriveDTO containerArriveDTO = new ContainerArriveDTO()
@@ -457,6 +712,7 @@
                };
                string request = JsonConvert.SerializeObject(containerArriveDTO, settings);
                string response = HttpHelper.Post(url, request);
                WriteLog.Write_Log("上报WMS料箱到达", "上报WMS料箱到达", "信息", $"请求:{request},回传:{response}");
                WMSResponseContent wMSResponse = JsonConvert.DeserializeObject<WMSResponseContent>(response) ?? throw new Exception($"{pickCode},未接收到WMS料箱到达拣选位上报返回值");
                if (wMSResponse.Code != "0") throw new Exception($"料箱{pickCode}WMS料箱到达拣选位上报错误,信息:{wMSResponse.Msg}");
                content.OK();
@@ -467,6 +723,9 @@
            }
            return content;
        }
        // åœ¨ç±»ä¸­æ·»åŠ é™æ€é”å¯¹è±¡
        private static readonly object _taskCompleteLock = new object();
        /// <summary>
        /// ä»»åŠ¡å®Œæˆ
        /// </summary>
@@ -475,94 +734,509 @@
        public WebResponseContent TaskCompleted(int taskNum)
        {
            WebResponseContent content = new WebResponseContent();
            // ä½¿ç”¨é”ç¡®ä¿åŒä¸€ä»»åŠ¡ä¸ä¼šå¹¶å‘å¤„ç†
            lock (_taskCompleteLock)
            {
                try
                {
                    WriteLog.Write_Log("任务完成", "任务完成接口", "任务号", $"任务:{taskNum}");
                    // å†æ¬¡æŸ¥è¯¢ä»»åŠ¡çŠ¶æ€ï¼Œé˜²æ­¢åœ¨é”ç­‰å¾…æœŸé—´ä»»åŠ¡çŠ¶æ€å·²æ”¹å˜
                    Dt_Task task = BaseDal.QueryFirst(x => x.TaskNum == taskNum);
                    if (task == null)
                    {
                        return content.Error($"任务{taskNum}不存在");
                    }
                    // æ£€æŸ¥ä»»åŠ¡çŠ¶æ€ï¼Œé¿å…é‡å¤å®Œæˆ
                    if (task.TaskState == TaskStatusEnum.Finish.ObjToInt())
                    {
                        return content.Error($"任务{taskNum}已完成,请勿重复操作");
                    }
                    if (task != null && task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup)//出库任务完成逻辑
                    {
                        Dt_LocationInfo locationInfo = _locationInfoRepository.QueryFirst(x => x.PalletCode == task.PalletCode);
                        if (locationInfo.LocationStatus != LocationStatusEnum.Lock.ObjToInt())
                        {
                            return content.Error($"{locationInfo.LocationCode}货位状态不正确");
                        }
                        task.TaskState = TaskStatusEnum.Finish.ObjToInt();
                        locationInfo.LocationStatus = LocationStatusEnum.Free.ObjToInt();
                        locationInfo.PalletCode = "";
                        //料箱出库完成上报给WMS
                        string? url = _apiInfoRepository.QueryFirst(x => x.ApiCode == APIEnum.WMSInOutBoundBack.ToString())?.ApiAddress;
                        if (string.IsNullOrEmpty(url))
                        {
                            _taskExecuteDetailService.AddTaskExecuteDetail(task, $"未找到WMS出库上报接口,请检查接口配置");
                            UpdateTaskExceptionMessage(taskNum, $"未找到WMS出库上报接口,请检查接口配置");
                            return content.Error($"{taskNum},未找到WMS出库上报接口,请检查接口配置");
                        }
                        ContainerInFinishDTO containerInFinishDTO = new ContainerInFinishDTO()
                        {
                            TaskCode = task.TaskNum.ToString(),
                            ContainerCode = task.PalletCode,
                            StationCode = task.TargetAddress,
                            LocationCode = task.SourceAddress,
                            CompleteType = 1
                        };
                        string request = JsonConvert.SerializeObject(containerInFinishDTO, settings);
                        _unitOfWorkManage.BeginTran();
                        _locationInfoRepository.UpdateData(locationInfo);
                        BaseDal.DeleteAndMoveIntoHty(task, App.User?.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                        _unitOfWorkManage.CommitTran();
                        _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, LocationStatusEnum.Lock, LocationStatusEnum.Free, LocationChangeType.OutboundCompleted, task.TaskNum);
                        //调用接口
                        string response = HttpHelper.Post(url, request);
                        WriteLog.Write_Log("WMS出库任务完成回传", "任务完成接口", "任务信息", $"请求:{request},回传:{response}");
                        WMSResponseContent wMSResponse = JsonConvert.DeserializeObject<WMSResponseContent>(response) ?? throw new Exception($"{taskNum},未接收到WMS出库上报返回值");
                        if (wMSResponse.Code != "0") content.Message = $"出库任务{task.TaskNum}WMS出库上报错误,信息:{wMSResponse.Msg}";
                    }
                    else if (task != null && task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.InboundGroup)//入库任务完成逻辑
                    {
                        string? url = _apiInfoRepository.QueryFirst(x => x.ApiCode == APIEnum.WMSInOutBoundBack.ToString())?.ApiAddress;
                        if (string.IsNullOrEmpty(url))
                        {
                            _taskExecuteDetailService.AddTaskExecuteDetail(task, $"未找到WMS入库上报接口,请检查接口配置");
                            UpdateTaskExceptionMessage(taskNum, $"未找到WMS入库上报接口,请检查接口配置");
                            return content.Error($"{taskNum},未找到WMS入库上报接口,请检查接口配置");
                        }
                        ContainerInFinishDTO containerInFinishDTO = new ContainerInFinishDTO()
                        {
                            TaskCode = task.TaskNum.ToString(),
                            ContainerCode = task.PalletCode,
                            StationCode = task.SourceAddress,
                            LocationCode = task.TargetAddress,
                            CompleteType = 2
                        };
                        string request = JsonConvert.SerializeObject(containerInFinishDTO, settings);
                        Dt_LocationInfo locationInfo = _locationInfoRepository.QueryFirst(x => x.LocationCode == task.TargetAddress);
                        if (locationInfo.LocationStatus != LocationStatusEnum.Lock.ObjToInt())
                        {
                            return content.Error($"{locationInfo.LocationCode}货位状态不正确");
                        }
                        task.TaskState = TaskStatusEnum.Finish.ObjToInt();
                        locationInfo.LocationStatus = LocationStatusEnum.InStock.ObjToInt();
                        locationInfo.PalletCode = task.PalletCode;
                        _unitOfWorkManage.BeginTran();
                        _locationInfoRepository.UpdateData(locationInfo);
                        BaseDal.DeleteAndMoveIntoHty(task, App.User?.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                        _unitOfWorkManage.CommitTran();
                        _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, LocationStatusEnum.Lock, LocationStatusEnum.InStock, LocationChangeType.InboundCompleted, task.TaskNum);
                        //调用接口
                        string response = HttpHelper.Post(url, request);
                        WriteLog.Write_Log("WMS入库任务完成回传", "任务完成接口", "任务信息", $"请求:{request},回传:{response}");
                        WMSResponseContent wMSResponse = JsonConvert.DeserializeObject<WMSResponseContent>(response) ?? throw new Exception($"{taskNum},未接收到WMS入库上报返回值");
                        if (wMSResponse.Code != "0") content.Message = $"入库任务{task.TaskNum}WMS入库上报错误,信息:{wMSResponse.Msg}";
                    }
                    content.OK("任务完成");
                }
                catch (Exception ex)
                {
                    _unitOfWorkManage.RollbackTran();
                    content.Error(ex.Message);
                }
                return content;
            }
        }
        ///// <summary>
        ///// ä»»åŠ¡å®Œæˆ
        ///// </summary>
        ///// <param name="taskNum"></param>
        ///// <returns></returns>
        //public WebResponseContent TaskCompleted(int taskNum)
        //{
        //    WebResponseContent content = new WebResponseContent();
        //    try
        //    {
        //        WriteLog.Write_Log("任务完成", "任务完成接口", "任务号", $"任务:{taskNum}");
        //        Dt_Task task = BaseDal.QueryFirst(x => x.TaskNum == taskNum);
        //        if (task != null && task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup)//出库任务完成逻辑
        //        {
        //            Dt_LocationInfo locationInfo = _locationInfoRepository.QueryFirst(x => x.PalletCode == task.PalletCode);
        //            if (locationInfo.LocationStatus != LocationStatusEnum.Lock.ObjToInt())
        //            {
        //                return content.Error($"{locationInfo.LocationCode}货位状态不正确");
        //            }
        //            task.TaskState = TaskStatusEnum.Finish.ObjToInt();
        //            locationInfo.LocationStatus = LocationStatusEnum.Free.ObjToInt();
        //            locationInfo.PalletCode = "";
        //            //料箱出库完成上报给WMS
        //            string? url = _apiInfoRepository.QueryFirst(x => x.ApiCode == APIEnum.WMSInOutBoundBack.ToString())?.ApiAddress;
        //            if (string.IsNullOrEmpty(url))
        //            {
        //                _taskExecuteDetailService.AddTaskExecuteDetail(task, $"未找到WMS出库上报接口,请检查接口配置");
        //                UpdateTaskExceptionMessage(taskNum, $"未找到WMS出库上报接口,请检查接口配置");
        //                return content.Error($"{taskNum},未找到WMS出库上报接口,请检查接口配置");
        //            }
        //            ContainerInFinishDTO containerInFinishDTO = new ContainerInFinishDTO()
        //            {
        //                TaskCode = task.TaskNum.ToString(),
        //                ContainerCode = task.PalletCode,
        //                StationCode = task.TargetAddress,
        //                LocationCode = task.SourceAddress,
        //                CompleteType = 1
        //            };
        //            string request = JsonConvert.SerializeObject(containerInFinishDTO, settings);
        //            _unitOfWorkManage.BeginTran();
        //            _locationInfoRepository.UpdateData(locationInfo);
        //            BaseDal.DeleteAndMoveIntoHty(task, App.User?.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
        //            _unitOfWorkManage.CommitTran();
        //            _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, LocationStatusEnum.Lock, LocationStatusEnum.Free, LocationChangeType.OutboundCompleted, task.TaskNum);
        //            //调用接口
        //            string response = HttpHelper.Post(url, request);
        //            WriteLog.Write_Log("WMS出库任务完成回传", "任务完成接口", "任务信息", $"请求:{request},回传:{response}");
        //            WMSResponseContent wMSResponse = JsonConvert.DeserializeObject<WMSResponseContent>(response) ?? throw new Exception($"{taskNum},未接收到WMS出库上报返回值");
        //            if (wMSResponse.Code != "0") content.Message = $"出库任务{task.TaskNum}WMS出库上报错误,信息:{wMSResponse.Msg}";
        //        }
        //        else if (task != null && task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.InboundGroup)//入库任务完成逻辑
        //        {
        //            string? url = _apiInfoRepository.QueryFirst(x => x.ApiCode == APIEnum.WMSInOutBoundBack.ToString())?.ApiAddress;
        //            if (string.IsNullOrEmpty(url))
        //            {
        //                _taskExecuteDetailService.AddTaskExecuteDetail(task, $"未找到WMS入库上报接口,请检查接口配置");
        //                UpdateTaskExceptionMessage(taskNum, $"未找到WMS入库上报接口,请检查接口配置");
        //                return content.Error($"{taskNum},未找到WMS入库上报接口,请检查接口配置");
        //            }
        //            ContainerInFinishDTO containerInFinishDTO = new ContainerInFinishDTO()
        //            {
        //                TaskCode = task.TaskNum.ToString(),
        //                ContainerCode = task.PalletCode,
        //                StationCode = task.SourceAddress,
        //                LocationCode = task.TargetAddress,
        //                CompleteType = 2
        //            };
        //            string request = JsonConvert.SerializeObject(containerInFinishDTO, settings);
        //            Dt_LocationInfo locationInfo = _locationInfoRepository.QueryFirst(x => x.LocationCode == task.TargetAddress);
        //            if (locationInfo.LocationStatus != LocationStatusEnum.Lock.ObjToInt())
        //            {
        //                return content.Error($"{locationInfo.LocationCode}货位状态不正确");
        //            }
        //            task.TaskState = TaskStatusEnum.Finish.ObjToInt();
        //            locationInfo.LocationStatus = LocationStatusEnum.InStock.ObjToInt();
        //            locationInfo.PalletCode = task.PalletCode;
        //            _unitOfWorkManage.BeginTran();
        //            _locationInfoRepository.UpdateData(locationInfo);
        //            BaseDal.DeleteAndMoveIntoHty(task, App.User?.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
        //            _unitOfWorkManage.CommitTran();
        //            _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, LocationStatusEnum.Lock, LocationStatusEnum.InStock, LocationChangeType.InboundCompleted, task.TaskNum);
        //            //调用接口
        //            string response = HttpHelper.Post(url, request);
        //            WriteLog.Write_Log("WMS入库任务完成回传", "任务完成接口", "任务信息", $"请求:{request},回传:{response}");
        //            WMSResponseContent wMSResponse = JsonConvert.DeserializeObject<WMSResponseContent>(response) ?? throw new Exception($"{taskNum},未接收到WMS入库上报返回值");
        //            if (wMSResponse.Code != "0") content.Message = $"入库任务{task.TaskNum}WMS入库上报错误,信息:{wMSResponse.Msg}";
        //        }
        //        content.OK("任务完成");
        //    }
        //    catch (Exception ex)
        //    {
        //        _unitOfWorkManage.RollbackTran();
        //        content.Error(ex.Message);
        //    }
        //    return content;
        //}
        /// <summary>
        /// äººå·¥æ‰‹åŠ¨å–æ¶ˆæŒ‡å®šä»»åŠ¡
        /// </summary>
        /// <param name="taskNum">任务编号</param>
        /// <returns>操作结果</returns>
        public WebResponseContent ManualTaskCancellation(int taskNum)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                WriteLog.Write_Log("任务取消接收", "人工手动取消指定任务", "任务号", $"任务:{taskNum}");
                // 1. èŽ·å–ä»»åŠ¡ä¿¡æ¯
                Dt_Task task = BaseDal.QueryFirst(x => x.TaskNum == taskNum);
                if (task != null && task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup)//出库任务完成逻辑
                if (task == null) return content.Error($"任务{taskNum}不存在");
                TaskTypeGroup group = task.TaskType.GetTaskTypeGroup();
                if (group == TaskTypeGroup.InboundGroup)// å…¥åº“任务取消
                {
                    Dt_LocationInfo locationInfo = _locationInfoRepository.QueryFirst(x=>x.PalletCode==task.PalletCode);
                    if (locationInfo.LocationStatus != LocationStatusEnum.Lock.ObjToInt())
                    {
                        return content.Error($"{locationInfo.LocationCode}货位状态不正确");
                    }
                    task.TaskState = TaskStatusEnum.Finish.ObjToInt();
                    locationInfo.LocationStatus = LocationStatusEnum.Free.ObjToInt();
                    locationInfo.PalletCode = "";
                    //料箱出库完成上报给WMS
                    string? url = _apiInfoRepository.QueryFirst(x => x.ApiCode == APIEnum.WMSInOutBoundBack.ToString())?.ApiAddress;
                    if (string.IsNullOrEmpty(url))
                    {
                        _taskExecuteDetailService.AddTaskExecuteDetail(task, $"未找到WMS出库上报接口,请检查接口配置");
                        UpdateTaskExceptionMessage(taskNum, $"未找到WMS出库上报接口,请检查接口配置");
                        return content.Error($"{taskNum},未找到WMS出库上报接口,请检查接口配置");
                    }
                    ContainerInFinishDTO containerInFinishDTO = new ContainerInFinishDTO()
                    {
                        TaskCode = task.TaskNum.ToString(),
                        ContainerCode = task.PalletCode,
                        StationCode = task.TargetAddress,
                        LocationCode = task.SourceAddress,
                        CompleteType = 1
                    };
                    string request = JsonConvert.SerializeObject(containerInFinishDTO, settings);
                    //调用接口
                    string response = HttpHelper.Post(url, request);
                    WMSResponseContent wMSResponse = JsonConvert.DeserializeObject<WMSResponseContent>(response) ?? throw new Exception($"{taskNum},未接收到WMS出库上报返回值");
                    if (wMSResponse.Code != "0") throw new Exception($"出库任务{task.TaskNum}WMS出库上报错误,信息:{wMSResponse.Msg}");
                    _unitOfWorkManage.BeginTran();
                    _locationInfoRepository.UpdateData(locationInfo);
                    BaseDal.DeleteAndMoveIntoHty(task, App.User?.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                    _unitOfWorkManage.CommitTran();
                }
                else if(task != null && task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.InboundGroup)//入库任务完成逻辑
                {
                    string? url = _apiInfoRepository.QueryFirst(x => x.ApiCode == APIEnum.WMSInOutBoundBack.ToString())?.ApiAddress;
                    if (string.IsNullOrEmpty(url))
                    {
                        _taskExecuteDetailService.AddTaskExecuteDetail(task, $"未找到WMS入库上报接口,请检查接口配置");
                        UpdateTaskExceptionMessage(taskNum, $"未找到WMS入库上报接口,请检查接口配置");
                        return content.Error($"{taskNum},未找到WMS入库上报接口,请检查接口配置");
                    }
                    ContainerInFinishDTO containerInFinishDTO = new ContainerInFinishDTO()
                    {
                        TaskCode = task.TaskNum.ToString(),
                        ContainerCode = task.PalletCode,
                        StationCode = task.SourceAddress,
                        LocationCode = task.TargetAddress,
                        CompleteType = 2
                    };
                    string request = JsonConvert.SerializeObject(containerInFinishDTO, settings);
                    //调用接口
                    string response = HttpHelper.Post(url, request);
                    WMSResponseContent wMSResponse = JsonConvert.DeserializeObject<WMSResponseContent>(response) ?? throw new Exception($"{taskNum},未接收到WMS入库上报返回值");
                    if (wMSResponse.Code != "0") throw new Exception($"入库任务{task.TaskNum}WMS入库上报错误,信息:{wMSResponse.Msg}");
                    // èŽ·å–ç›®æ ‡è´§ä½
                    Dt_LocationInfo locationInfo = _locationInfoRepository.QueryFirst(x => x.LocationCode == task.TargetAddress);
                    if (locationInfo.LocationStatus != LocationStatusEnum.Lock.ObjToInt())
                    if (locationInfo != null)
                    {
                        return content.Error($"{locationInfo.LocationCode}货位状态不正确");
                        locationInfo.LocationStatus = LocationStatusEnum.Free.ObjToInt(); // æ¢å¤ä¸ºç©ºé—²çŠ¶æ€
                        locationInfo.PalletCode = ""; // æ¸…空托盘号
                        _unitOfWorkManage.BeginTran();
                        _locationInfoRepository.UpdateData(locationInfo);
                        _unitOfWorkManage.CommitTran();
                        content.OK("任务取消成功");
                    }
                    task.TaskState = TaskStatusEnum.Finish.ObjToInt();
                    locationInfo.LocationStatus = LocationStatusEnum.InStock.ObjToInt();
                    locationInfo.PalletCode = task.PalletCode;
                    _unitOfWorkManage.BeginTran();
                    _locationInfoRepository.UpdateData(locationInfo);
                    BaseDal.DeleteAndMoveIntoHty(task, App.User?.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                    BaseDal.DeleteAndMoveIntoHty(task, OperateTypeEnum.人工删除);
                    _unitOfWorkManage.CommitTran();
                    //return content.Error($"目标货位{task.TargetAddress}不存在");
                    // éªŒè¯è´§ä½çŠ¶æ€
                    //if (locationInfo.LocationStatus != LocationStatusEnum.Lock.ObjToInt())
                    //    return content.Error($"{task.TargetAddress}货位状态异常,无法取消");
                    // æ¢å¤è´§ä½çŠ¶æ€
                    // æ›´æ–°æ•°æ®åº“
                    //_unitOfWorkManage.BeginTran();
                    //_locationInfoRepository.UpdateData(locationInfo);
                    //BaseDal.DeleteAndMoveIntoHty(task, OperateTypeEnum.人工删除);
                    //_unitOfWorkManage.CommitTran();
                    // è®°å½•状态变更
                    content.OK("任务取消成功");
                }
                content.OK("任务完成");
                else
                {
                    content.Error("只能入库任务取消!");
                }
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                content.Error($"取消失败: {ex.Message}");
                // è®°å½•详细错误
                _taskExecuteDetailService.AddTaskExecuteDetail(
                    new Dt_Task { TaskNum = taskNum },
                    $"任务取消异常: {ex.Message}"
                );
            }
            return content;
        }
        /// <summary>
        /// ä»»åŠ¡å–æ¶ˆ
        /// </summary>
        /// <returns></returns>
        public WebResponseContent TaskCancelCompleted(int taskNum)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                WriteLog.Write_Log("任务取消接收", "任务取消接口", "任务号", $"任务:{taskNum}");
                Dt_Task task = BaseDal.QueryFirst(x => x.TaskNum == taskNum);
                if (task != null && task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup)//出库任务完成逻辑
                {
                    Dt_LocationInfo locationInfo = _locationInfoRepository.QueryFirst(x => x.PalletCode == task.PalletCode);
                    if (locationInfo.LocationStatus != LocationStatusEnum.Lock.ObjToInt())
                    {
                        return content.Error($"{locationInfo.LocationCode}货位状态不正确");
                    }
                    task.TaskState = TaskStatusEnum.Cancel.ObjToInt();
                    locationInfo.LocationStatus = LocationStatusEnum.InStock.ObjToInt();
                    _unitOfWorkManage.BeginTran();
                    _locationInfoRepository.UpdateData(locationInfo);
                    BaseDal.DeleteAndMoveIntoHty(task, App.User?.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                    _unitOfWorkManage.CommitTran();
                    _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, LocationStatusEnum.Lock, LocationStatusEnum.InStock, LocationChangeType.InboundCompleted, task.TaskNum);
                    content.OK();
                }
                else
                {
                    content.Error($"未找到出库任务{taskNum}");
                }
            }
            catch (Exception ex)
            {
                content.Error(ex.Message);
            }
            return content;
        }
        /// <summary>
        /// ä»»åŠ¡å–æ¶ˆ
        /// </summary>
        /// <returns></returns>
        public WebResponseContent TaskCancel(List<TaskCancel> taskCancels)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                // å‚数验证
                if (taskCancels == null || taskCancels.Count == 0)
                {
                    return content.Error("传入参数不能为空");
                }
                WriteLog.Write_Log("任务取消接收", "任务取消接口", "任务取消", $"任务:{taskCancels.ToJson()}");
                // èŽ·å–æ‰€æœ‰å‡ºåº“ä»»åŠ¡ï¼ˆåªæŸ¥è¯¢ä¸€æ¬¡ï¼‰
                List<Dt_Task> outTasks = BaseDal.QueryData(x =>
                    x.TaskType == TaskTypeEnum.Outbound.ObjToInt());
                if (outTasks.Count == 0)
                {
                    return content.Error("未找到对应的任务");
                }
                // æŒ‰GroupId分组处理
                var tasksByGroup = outTasks.GroupBy(x => x.GroupId)
                                           .Where(g => !string.IsNullOrEmpty(g.Key))
                                           .ToDictionary(g => g.Key, g => g.ToList());
                List<Dt_Task> cancelTasks = new List<Dt_Task>();
                List<Dt_Task> cancelTasksCompleted = new List<Dt_Task>();
                // æ”¶é›†æ‰€æœ‰éœ€è¦æ£€æŸ¥çš„任务组
                var groupsToCheck = new List<List<Dt_Task>>();
                foreach (var taskCancel in taskCancels)
                {
                    // æ‰¾åˆ°è¯¥ä»»åŠ¡æ‰€åœ¨çš„ç»„
                    var group = tasksByGroup.Values.FirstOrDefault(g =>
                        g.Any(t => t.PalletCode == taskCancel.ContainerCode));
                    if (group != null && !groupsToCheck.Contains(group))
                    {
                        groupsToCheck.Add(group);
                    }
                }
                // éªŒè¯ä»»åŠ¡çŠ¶æ€
                foreach (var group in groupsToCheck)
                {
                    var firstTask = group.FirstOrDefault();
                    if (firstTask == null) continue;
                    // æ£€æŸ¥ç»„内所有任务状态
                    foreach (var task in group)
                    {
                        if (task.TaskState == TaskStatusEnum.AGV_TakeFinish.ObjToInt())
                        {
                            task.IsCancel = 1;
                            cancelTasks.Add(task);
                        }
                        else if (task.TaskState == TaskStatusEnum.AGV_Executing.ObjToInt())
                        {
                            cancelTasksCompleted.Add(task);
                        }
                        else
                        {
                            return content.Error($"任务取消失败{task.PalletCode}任务状态不可取消!");
                        }
                    }
                }
                //WriteLog.Write_Log("任务取消接收", "任务取消接口", "任务取消", $"任务:{taskCancels.ToJson()}");
                //if (taskCancels==null || taskCancels.Count<=0)
                //{
                //    return content.Error("传入不能为空");
                //}
                ////获取所有料箱
                //List<Dt_Task> outTasks = BaseDal.QueryData(x=>x.TaskType==TaskTypeEnum.Outbound.ObjToInt());
                //List<Dt_Task> cancelTasks = new List<Dt_Task>();
                //List<Dt_Task> cancelTasksCompleted = new List<Dt_Task>();
                //HashSet<string> processedGroups = new HashSet<string>();
                ////判断是否有任务存在
                //foreach (var item in taskCancels)
                //{
                //    Dt_Task? taskExist = outTasks.FirstOrDefault(x=>x.PalletCode == item.ContainerCode);
                //    if (taskExist==null)
                //    {
                //        content.Message += $"{item.ContainerCode}任务不存在";
                //        WriteLog.Write_Log("任务取消接收", "任务取消接口", "任务不存在", $"任务:{item.ContainerCode}");
                //        continue;
                //    }
                //    if (string.IsNullOrEmpty(taskExist.GroupId))
                //    {
                //        continue;
                //    }
                //    processedGroups.Add(taskExist.GroupId);
                //    //if (taskExist.TaskState == TaskStatusEnum.AGV_TakeFinish.ObjToInt())
                //    //{
                //    //    taskExist.IsCancel = 1;
                //    //    cancelTasks.Add(taskExist);
                //    //}
                //    //else if(taskExist.TaskState == TaskStatusEnum.AGV_Executing.ObjToInt())
                //    //{
                //    //    cancelTasksCompleted.Add(taskExist);
                //    //}
                //    //else
                //    //{
                //    //    return content.Error($"任务取消失败{item.TaskCode}任务状态不可取消!");
                //    //}
                //}
                //// å–消整个组
                //foreach(var processed in processedGroups)
                //{
                //    List<Dt_Task> groupTask = BaseDal.QueryData(x => x.TaskType == TaskTypeEnum.Outbound.ObjToInt() && x.GroupId == processed);
                //    foreach (var group in groupTask)
                //    {
                //        if (group.TaskState == TaskStatusEnum.AGV_TakeFinish.ObjToInt())
                //        {
                //            group.IsCancel = 1;
                //            cancelTasks.Add(group);
                //        }
                //        else if (group.TaskState == TaskStatusEnum.AGV_Executing.ObjToInt())
                //        {
                //            cancelTasksCompleted.Add(group);
                //        }
                //        else
                //        {
                //            return content.Error($"任务取消失败{group.PalletCode}任务状态不可取消!");
                //        }
                //    }
                //}
                _unitOfWorkManage.BeginTran();
                BaseDal.UpdateData(cancelTasks);
                foreach (var item in cancelTasksCompleted)
                {
                    WebResponseContent responseContent = TaskCancelCompleted(item.TaskNum);
                    if (!responseContent.Status)
                    {
                        throw new Exception(responseContent.Message);
                    }
                }
                _unitOfWorkManage.CommitTran();
                cancelTasks.AddRange(cancelTasksCompleted);
                foreach (var item in cancelTasks)
                {
                    AgvTaskCancelDTO agvTaskCancel = new AgvTaskCancelDTO()
                    {
                        RequestId = DateTime.Now.ToString("yyMMddHHmmssfff"),
                        MissionCode = item.GroupId,
                        ContainerCode = item.PalletCode,
                        Position = "",
                        CancelMode = "CTU_REDIRECT_START",
                        Reason = ""
                    };
                    AgvCancelTask(agvTaskCancel);
                }
                content.OK();
            }
            catch (Exception ex)
            {
                content.Error(ex.Message);
            }
            return content;
        }
        /// <summary>
        /// äºŒæœŸæ’­ç§å¢™å›žä¼ 
        /// </summary>
        /// <returns></returns>
        public EPLightContent WMSLightBack(List<TaskBackLight> taskBackLights)
        {
            EPLightContent content = new EPLightContent();
            try
            {
                string? url = _apiInfoRepository.QueryFirst(x => x.ApiCode == APIEnum.WMSLightBack.ToString())?.ApiAddress;
                if (string.IsNullOrEmpty(url))
                {
                    return content.Error($"未找到播种墙上报,请检查接口配置");
                }
                string request = JsonConvert.SerializeObject(taskBackLights, settings);
                string response = HttpHelper.Post(url, request);
                WMSResponseContent wMSResponse = JsonConvert.DeserializeObject<WMSResponseContent>(response) ?? throw new Exception($"未接收到播种墙上报返回值");
                if (wMSResponse.Code != "0") throw new Exception($"播种墙上报错误,信息:{wMSResponse.Msg}");
                content.OK();
            }
            catch (Exception ex)
            {
                content.Error(ex.Message);
            }
            return content;
        }
        /// <summary>
        /// äºŒæœŸæ’­ç§å¢™ä¸‹å‘
        /// </summary>
        /// <param name="taskNum"></param>
        /// <returns></returns>
        public EPLightContent PickOrderInfoRequest(List<EPLightSendDTO> lightSendDTOs)
        {
@@ -574,8 +1248,8 @@
                {
                    return content.Error($"未找到播种墙下发接口,请检查接口配置");
                }
                string request = JsonConvert.SerializeObject(lightSendDTOs, settings);
                //调用接口
                string request = JsonConvert.SerializeObject(lightSendDTOs, settings).ToUpper();
                // è°ƒç”¨æŽ¥å£
                string response = HttpHelper.Post(url, request);
                EPLightContent lightContent = JsonConvert.DeserializeObject<EPLightContent>(response) ?? throw new Exception($"未接收到播种墙下发上报返回值");
                if (lightContent.Result != "0") throw new Exception($"播种墙下发错误,信息:{lightContent.Msg}");
@@ -641,5 +1315,98 @@
            }
            return content;
        }
        public override WebResponseContent Export(PageDataOptions options)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                string savePath = AppDomain.CurrentDomain.BaseDirectory + "ExcelExport";
                // ç¡®ä¿ç›®å½•存在
                if (!Directory.Exists(savePath))
                    Directory.CreateDirectory(savePath);
                // èŽ·å–æ•°æ®
                ISugarQueryable<Dt_Task> query = BaseDal.Db.Queryable<Dt_Task>();
                var dataList = query.ToList();
                var properties = typeof(Dt_Task).GetProperties();
                string filePath = TExportHelper.GetExport(savePath, properties, dataList);
                return WebResponseContent.Instance.OK(data: filePath);
            }
            catch (Exception ex)
            {
                content = WebResponseContent.Instance.Error(ex.Message);
            }
            return content;
        }
        /// <summary>
        /// é‡ç½®æ‰€æœ‰å¼‚常任务
        /// </summary>
        public WebResponseContent ResetAllExceptionTask(int taskNum)
        {
            // èŽ·å–å¼‚å¸¸ä»»åŠ¡990修改为AGV待执行300
            WebResponseContent content = new WebResponseContent();
            try
            {
                Dt_Task task = BaseDal.QueryFirst(x => x.TaskNum == taskNum);
                if (task == null) return WebResponseContent.Instance.Error($"未找到该任务信息,任务号:【{taskNum}】");
                if (task.TaskState != (int)TaskStatusEnum.Exception)
                {
                    return content = WebResponseContent.Instance.Error($"该任务状态不可重置,任务号:【{taskNum}】,任务状态:【{task.TaskState}】");
                }
                task.TaskState = (int)TaskStatusEnum.AGV_Execute;
                BaseDal.UpdateData(task);
                //_taskExecuteDetailService.AddTaskExecuteDetail(task, $"人工重置异常任务,重置后任务状态【{task.TaskState}】");
                content = WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
            {
                content.Error(ex.Message);
            }
            return content;
        }
        public WebResponseContent WmsRecovery()
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                // åˆ é™¤ç¬¬ä¸€ä¸ªå¼‚常
                // æŒ‰åˆ›å»ºæ—¶é—´å‡åºèŽ·å–ç¬¬ä¸€æ¡è®°å½•
                var orderBy = new Dictionary<string, OrderByType>
                {
                    { "CreateDate", OrderByType.Asc }
                };
                Dt_ErrorInfo errorInfo = _errorInfoRepository.QueryFirst(x => true, orderBy);
                if (errorInfo == null)
                {
                    return content.Error("当前没有异常任务");
                }
                // èŽ·å–ç¬¬ä¸€ä¸ªå¼‚å¸¸ï¼ˆæŒ‰åˆ›å»ºæ—¶é—´æŽ’åºï¼‰
                _unitOfWorkManage.BeginTran();
                _errorInfoRepository.DeleteData(errorInfo);
                _unitOfWorkManage.CommitTran();
                // ä¸ŠæŠ¥æ¢å¤
                string? apiErrorBack = _apiInfoRepository.QueryFirst(x => x.ApiCode == APIEnum.WMSErrorBack.ToString())?.ApiAddress;
                if (string.IsNullOrEmpty(apiErrorBack)) throw new Exception($"未找到WMS故障上报,请检查接口配置");
                TaskError taskError = new TaskError()
                {
                    MsgID = errorInfo.Id,
                    StationCode = errorInfo.StationCode,
                    MsgCode = 0,
                    Msg = "恢复"
                };
                string reqErrorBack = JsonConvert.SerializeObject(taskError, settings);
                HttpHelper.Post(apiErrorBack, reqErrorBack);
                return content.OK();
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return content.Error(ex.Message);
                throw new Exception(ex.Message);
            }
        }
    }
}