1
z8018
2025-04-08 e69f814f50fd59739dbedd88518dc8cb8d2ed3ee
ÏîÄ¿´úÂë/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs
@@ -16,851 +16,268 @@
#endregion << ç‰ˆ æœ¬ æ³¨ é‡Š >>
using AutoMapper;
using Magicodes.ExporterAndImporter.Core;
using Microsoft.AspNetCore.Mvc.RazorPages;
using NetTaste;
using Newtonsoft.Json;
using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using HslCommunication.WebSocket;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Metadata;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using WIDESEA_Comm.Http;
using WIDESEA_Common.Log;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_BasicInfoRepository;
using WIDESEAWCS_BasicInfoService;
using WIDESEAWCS_Common;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseServices;
using WIDESEAWCS_Core.Enums;
using WIDESEAWCS_Core.Utilities;
using WIDESEAWCS_DTO.Enum;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_IBasicInfoRepository;
using WIDESEAWCS_ITaskInfoRepository;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob.Models;
using WIDESEAWCS_QuartzJob.Service;
using static Microsoft.IO.RecyclableMemoryStreamManager;
using WIDESEAWCS_QuartzJob.Repository;
namespace WIDESEAWCS_TaskInfoService
{
    public class TaskService : ServiceBase<Dt_Task, ITaskRepository>, ITaskService
    {
        private readonly IRouterService _routerService;
        private readonly ITaskExecuteDetailService _taskExecuteDetailService;
        private readonly ITaskExecuteDetailRepository _taskExecuteDetailRepository;
        private readonly ITask_HtyService _task_HtyService;
        private readonly IMapper _mapper;
        private readonly IContainerRepository _containerRepository;
        private readonly IContainerItemRepository _containerItemRepository;
        private readonly WebSocketServer _webSocketServer;
        private readonly IOrderDetailsRepository _orderDetailsRepository;
        private Dictionary<string, OrderByType> _taskOrderBy = new()
            {
                {nameof(Dt_Task.Grade),OrderByType.Desc },
                {nameof(Dt_Task.CreateDate),OrderByType.Asc},
            };
        public Dictionary<string, OrderByType> TaskOrderBy { get { return _taskOrderBy; } set { _taskOrderBy = value; } }
        public List<int> TaskInboundTypes => typeof(TaskInboundTypeEnum).GetEnumIndexList();
        public List<int> TaskOutboundTypes => typeof(TaskOutboundTypeEnum).GetEnumIndexList();
        public TaskService(ITaskRepository BaseDal, IRouterService routerService, ITaskExecuteDetailService taskExecuteDetailService, ITaskExecuteDetailRepository taskExecuteDetailRepository, IMapper mapper, ITask_HtyService task_HtyService) : base(BaseDal)
        public TaskService(ITaskRepository BaseDal, IMapper mapper, IContainerRepository containerRepository, IContainerItemRepository containerItemRepository, WebSocketServer webSocketServer, IOrderDetailsRepository orderDetailsRepository) : base(BaseDal)
        {
            _routerService = routerService;
            _taskExecuteDetailService = taskExecuteDetailService;
            _taskExecuteDetailRepository = taskExecuteDetailRepository;
            _task_HtyService = task_HtyService;
            _mapper = mapper;
            _containerRepository = containerRepository;
            _containerItemRepository = containerItemRepository;
            _webSocketServer = webSocketServer;
            _orderDetailsRepository = orderDetailsRepository;
        }
        /// <summary>
        /// æŽ¥æ”¶WMS任务信息
        /// </summary>
        /// <param name="taskDTOs">WMS任务对象集合</param>
        /// <returns>返回处理结果</returns>
        public WebResponseContent ReceiveWMSTask(Dt_Task taskDTOs)
        public Dt_Task? QueryAGantryUnExecuteTask(string gantryDeviceNo)
        {
            WebResponseContent content = new WebResponseContent();
            return BaseDal.QueryFirst(x => x.TaskState == (int)TaskStatusEnum.Gantry_New && x.DeviceCode == gantryDeviceNo);
        }
        public WebResponseContent PlaceBlockTest(int orderRowId)
        {
            try
            {
                BaseDal.AddData(taskDTOs);
                content = WebResponseContent.Instance.OK("成功");
            }
            catch (Exception ex)
            {
                content = WebResponseContent.Instance.Error($"生成任务失败,错误信息:{ex.Message}");
            }
            finally
            {
                WriteLog.GetLog("生成任务").Write(JsonConvert.SerializeObject(content), "生成任务");
            }
            return content;
        }
        /// <summary>
        /// æŸ¥æ‰¾è¯¥ç«™å°æ˜¯å¦æœ‰ä»»åŠ¡
        /// </summary>
        /// <param name="deviceNo">设备编号</param>
        /// <param name="currentAddress">当前地址</param>
        /// <returns></returns>
        public List<string> QueryConveyorLineTaskSourceAddress()
        {
            return BaseDal.QueryData().Select(task => task.SourceAddress).ToList();
        }
        /// <summary>
        /// ä¿®æ”¹ä»»åŠ¡ï¼Œæ·»åŠ ç›®æ ‡åœ°å€
        /// </summary>
        /// <param name="deviceNo">设备编号</param>
        /// <param name="currentAddress">当前地址</param>
        /// <returns></returns>
        public WebResponseContent UpdateTargetAddress(int TaskId,string TargetAddress)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                Dt_Task dt_Task = BaseDal.QueryFirst(x => x.TaskId == TaskId);
                dt_Task.TargetAddress = TargetAddress;
                dt_Task.NextAddress = TargetAddress;
                BaseDal.UpdateData(dt_Task);
                content = WebResponseContent.Instance.OK("成功");
            }
            catch (Exception ex)
            {
                content = WebResponseContent.Instance.Error($"任务接收错误,错误信息:{ex.Message}");
            }
            finally
            {
                WriteLog.GetLog("接收任务").Write(JsonConvert.SerializeObject(content), "接收任务");
            }
            return content;
        }
        /// <summary>
        /// æŸ¥æ‰¾æ˜¯å¦æœ‰ä»»åŠ¡å¯ä»¥æ”¾åœ¨è¯¥ä½ç½®
        /// </summary>
        /// <param name="deviceNo">设备编号</param>
        /// <param name="currentAddress">当前地址</param>
        /// <returns></returns>
        public Dt_Task QueryConveyorLineTaskRoadway(int agvarea)
        {
            return BaseDal.QueryFirst(x => x.Roadway == agvarea.ToString() && x.MaterialType == (int)AgvStationEnum.BoardUnload && x.TargetAddress =="");
        }
        public bool QueryConveyorLinetaeersuadd(string taeersuadd)
        {
            Dt_Task dt_= BaseDal.QueryFirst(x => x.SourceAddress == taeersuadd || x.TargetAddress == taeersuadd);
            if(dt_==null) return true;
            else return false;
        }
        /// <summary>
        /// æ ¹æ®è®¾å¤‡ç¼–号、当前地址查询输送线未执行的任务
        /// </summary>
        /// <param name="deviceNo">设备编号</param>
        /// <param name="currentAddress">当前地址</param>
        /// <returns></returns>
        public Dt_Task QueryConveyorLineTask(string deviceNo, string currentAddress)
        {
            return BaseDal.QueryFirst(x => (TaskInboundTypes.Contains(x.TaskType) && x.TaskState == (int)TaskInStatusEnum.InNew || TaskOutboundTypes.Contains(x.TaskType) && x.TaskState == (int)TaskOutStatusEnum.SC_OutFinish) && x.CurrentAddress == currentAddress, TaskOrderBy);
        }
        /// <summary>
        /// æ ¹æ®ä»»åŠ¡å·ã€ä¸‹ä¸€åœ°å€æŸ¥è¯¢è¾“é€çº¿æ‰§è¡Œä¸­çš„ä»»åŠ¡
        /// </summary>
        /// <param name="taskNum">任务号</param>
        /// <param name="nextAddress">下一地址</param>
        /// <returns></returns>
        public Dt_Task QueryExecutingConveyorLineTask(int taskNum, string nextAddress)
        {
            return BaseDal.QueryFirst(x => x.TaskNum == taskNum && x.NextAddress == nextAddress && (x.TaskState == (int)TaskInStatusEnum.Line_InExecuting || x.TaskState == (int)TaskOutStatusEnum.Line_OutExecuting), TaskOrderBy);
        }
        /// <summary>
        /// æ ¹æ®ä»»åŠ¡å·ã€å½“å‰åœ°å€æŸ¥è¯¢è¾“é€çº¿å®Œæˆçš„ä»»åŠ¡
        /// </summary>
        /// <param name="taskNum">任务号</param>
        /// <param name="currentAddress">当前地址</param>
        /// <returns></returns>
        public Dt_Task QueryCompletedConveyorLineTask(int taskNum, string currentAddress)
        {
            return BaseDal.QueryFirst(x => x.TaskNum == taskNum && x.CurrentAddress == currentAddress && (x.TaskState == (int)TaskInStatusEnum.Line_InFinish || x.TaskState == (int)TaskOutStatusEnum.Line_OutFinish), TaskOrderBy);
        }
        /// <summary>
        /// æ ¹æ®è®¾å¤‡ç¼–号、任务类型分组(可选)按照优先级以及创建时间排序查询任务池新增的任务
        /// </summary>
        /// <param name="deviceNo">设备编号</param>
        /// <param name="taskTypeGroup">任务类型分组(可选)</param>
        /// <returns></returns>
        public Dt_Task? QuertStackerCraneTask(string deviceNo, TaskTypeGroup? taskTypeGroup = null)
        {
            if(taskTypeGroup == null)
                return BaseDal.QueryFirst(x => x.Roadway == deviceNo && (TaskInboundTypes.Contains(x.TaskType) && x.TaskState == (int)TaskInStatusEnum.Line_InFinish || TaskOutboundTypes.Contains(x.TaskType) && x.TaskState == (int)TaskOutStatusEnum.OutNew), TaskOrderBy);
            if(taskTypeGroup.Value == TaskTypeGroup.InboundGroup)
                return BaseDal.QueryFirst(x => x.Roadway == deviceNo && TaskInboundTypes.Contains(x.TaskType) && x.TaskState == (int)TaskInStatusEnum.Line_InFinish, TaskOrderBy);
            if(taskTypeGroup.Value == TaskTypeGroup.OutbondGroup)
                return BaseDal.QueryFirst(x => x.Roadway == deviceNo && TaskOutboundTypes.Contains(x.TaskType) && x.TaskState == (int)TaskOutStatusEnum.OutNew, TaskOrderBy);
            return null;
        }
        /// <summary>
        /// æ ¹æ®è®¾å¤‡ç¼–号、当前地址按照优先级以及创建时间排序查询任务池新增的任务
        /// </summary>
        /// <param name="deviceNo">设备编号</param>
        /// <param name="currentAddress">当前地址</param>
        /// <returns>返回任务实体对象,可能为null</returns>
        public Dt_Task QueryStackerCraneTask(string deviceNo, string currentAddress = "")
        {
            return BaseDal.QueryFirst(x => x.TaskState == (int)TaskOutStatusEnum.OutNew && (deviceNo == "AGV01" ? x.Roadway == AgvareaEnum.AreaOne.ToString() : x.Roadway != AgvareaEnum.AreaOne.ToString()),TaskOrderBy);
        }
        public Dt_Task IngStackerCraneTask(string deviceNo)
        {
            //string deviceNot = deviceNo == "SC01" ? "1" : "2";
            return BaseDal.QueryFirst(x => x.Roadway == deviceNo && x.TaskState == (int)TaskInStatusEnum.SC_InExecuting);
        }
        public Dt_Task IngStackerCraneTask2(string deviceNo)
        {
            //string deviceNot = deviceNo == "SC01" ? "1" : "2";
            try
            {
                return BaseDal.QueryFirst(x => x.Roadway == deviceNo && x.TaskState == (int)TaskOutStatusEnum.SC_OutExecuting);
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        /// <summary>
        /// æ ¹æ®è®¾å¤‡ç¼–号、当前地址按照优先级以及创建时间排序查询任务池入库类型的新增的任务
        /// </summary>
        /// <param name="deviceNo">设备编号</param>
        /// <param name="currentAddress">当前地址</param>
        /// <returns>返回任务实体对象,可能为null</returns>
        public Dt_Task QueryStackerCraneInTask(string deviceNo, string currentAddress = "")
        {
            if (string.IsNullOrEmpty(currentAddress))
                return BaseDal.QueryFirst(x => x.Roadway == deviceNo && TaskInboundTypes.Contains(x.TaskType) && x.TaskState == (int)TaskInStatusEnum.Line_InFinish, TaskOrderBy);
            else
                return BaseDal.QueryFirst(x => x.Roadway == deviceNo && TaskInboundTypes.Contains(x.TaskType) && x.TaskState == (int)TaskInStatusEnum.Line_InFinish && x.CurrentAddress == currentAddress, TaskOrderBy);
        }
        /// <summary>
        /// æ ¹æ®è®¾å¤‡ç¼–号、当前地址按照优先级以及创建时间排序查询任务池出库类型的新增的任务
        /// </summary>
        /// <param name="deviceNo">设备编号</param>
        /// <param name="currentAddress">当前地址</param>
        /// <returns>返回任务实体对象,可能为null</returns>
        public Dt_Task QueryStackerCraneOutTask(string deviceNo, string currentAddress = "")
        {
            if (string.IsNullOrEmpty(currentAddress))
                return BaseDal.QueryFirst(x => x.Roadway == deviceNo && TaskOutboundTypes.Contains(x.TaskType) && x.TaskState == (int)TaskOutStatusEnum.OutNew, TaskOrderBy);
            else
                return BaseDal.QueryFirst(x => x.Roadway == deviceNo && TaskOutboundTypes.Contains(x.TaskType) && x.TaskState == (int)TaskOutStatusEnum.OutNew && x.CurrentAddress == currentAddress, TaskOrderBy);
        }
        /// <summary>
        /// æ ¹æ®è®¾å¤‡ç¼–号、当前地址按照优先级以及创建时间排序查询任务池出库类型的新增的任务
        /// </summary>
        /// <param name="deviceNo">设备编号</param>
        /// <param name="currentAddress">当前地址</param>
        /// <returns>返回任务实体对象集合,可能为null</returns>
        public List<Dt_Task> QueryStackerCraneOutTasks(string deviceNo, List<string> outStationCodes)
        {
            return BaseDal.QueryData(x => x.Roadway == deviceNo && TaskOutboundTypes.Contains(x.TaskType) && x.TaskState == (int)TaskOutStatusEnum.OutNew && outStationCodes.Contains(x.CurrentAddress), TaskOrderBy);
        }
        /// <summary>
        /// æ ¹æ®å‡ºåº“货位查询是否有当前浅货位任务
        /// </summary>
        /// <param name="deviceNo">设备编号</param>
        /// <param name="currentAddress">当前地址</param>
        /// <returns>返回任务实体对象集合,可能为null</returns>
        public List<Dt_Task> QueryStationIsOccupiedOutTasks(string deviceNo, string SourceAddress)
        {
            return BaseDal.QueryData(x => x.Roadway == deviceNo && SourceAddress.Contains(x.SourceAddress), TaskOrderBy);
        }
        /// <summary>
        /// æ›´æ–°ä»»åŠ¡å¼‚å¸¸ä¿¡æ¯æ˜¾ç¤º
        /// </summary>
        /// <param name="taskNum">任务号</param>
        /// <param name="message">异常信息</param>
        public WebResponseContent UpdateTaskExceptionMessage(int taskNum, string message)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                Dt_Task task = BaseDal.QueryFirst(x => x.TaskNum == taskNum);
                if (task == null) return WebResponseContent.Instance.Error($"未找到该任务信息,任务号:【{taskNum}】");
                if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup)
                List<OrderDetails> orderDetails = _orderDetailsRepository.QueryData(x => x.Orderrowsid == orderRowId);
                if (orderDetails == null || orderDetails.Count == 0)
                {
                    task.TaskState = (int)TaskOutStatusEnum.OutPending;
                    return WebResponseContent.Instance.Error("未找到订单明细信息");
                }
                else if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.InboundGroup)
                Dt_Container putContainer = _containerRepository.QueryFirst(x => x.ContainerType == ContainerTypeEnum.PutContainer.ObjToInt());
                if (putContainer == null)
                {
                    task.TaskState = (int)TaskInStatusEnum.InPending;
                    return WebResponseContent.Instance.Error("放货位置不存在");
                }
                task.ExceptionMessage = message;
                task.ModifyDate = DateTime.Now;
                BaseDal.UpdateData(task);
                _taskExecuteDetailService.AddTaskExecuteDetail(task.TaskId, task.ExceptionMessage);
                ContainerSize containerSize = new ContainerSize(1500, putContainer.ContainerWidth, putContainer.ContainerHeight);
                List<PlacedBlock> placedBlocks = new List<PlacedBlock>();
                content = WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
            {
                content = WebResponseContent.Instance.Error(ex.Message);
            }
            return content;
        }
        /// <summary>
        /// æ›´æ–°ä»»åŠ¡çŠ¶æ€ä¿¡æ¯ï¼Œå¹¶åŒæ­¥è‡³WMS
        /// </summary>
        /// <param name="taskNum">任务号</param>
        /// <param name="status">任务状态</param>
        public void UpdateTaskStatus(int taskNum, int status)
        {
            Dt_Task task = BaseDal.QueryFirst(x => x.TaskNum == taskNum);
            if (task == null) return;
            task.TaskState = status;
            task.ModifyDate = DateTime.Now;
            BaseDal.UpdateData(task);
        }
        /// <summary>
        /// å°†ä»»åŠ¡çŠ¶æ€ä¿®æ”¹ä¸ºä¸‹ä¸€ä¸ªçŠ¶æ€
        /// </summary>
        /// <param name="taskNum">任务号</param>
        public WebResponseContent UpdateTaskStatusToNext(int taskNum)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                Dt_Task task = BaseDal.QueryFirst(x => x.TaskNum == taskNum);
                if (task == null) return WebResponseContent.Instance.Error($"未找到该任务信息,任务号:【{taskNum}】");
                return UpdateTaskStatusToNext(task);
            }
            catch (Exception ex)
            {
                content = WebResponseContent.Instance.Error(ex.Message);
            }
            return content;
        }
        /// <summary>
        /// å°†ä»»åŠ¡çŠ¶æ€ä¿®æ”¹ä¸ºä¸‹ä¸€ä¸ªçŠ¶æ€
        /// </summary>
        /// <param name="task">任务实体对象</param>
        /// <returns></returns>
        public WebResponseContent UpdateTaskStatusToNext([NotNull] Dt_Task task)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                int oldState = task.TaskState;
                if (task.TaskType == (int)TaskOutboundTypeEnum.Outbound)
                for (int i = 0; i < orderDetails.Count; i++)
                {
                    if (task.TaskState >= (int)TaskOutStatusEnum.OutFinish)
                    try
                    {
                        return content = WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskState}】");
                    }
                    int nextStatus = task.TaskState.GetNextNotCompletedStatus<TaskOutStatusEnum>();
                    task.TaskState = nextStatus;
                    if (task.TaskState == (int)TaskOutStatusEnum.SC_OutExecuting)
                    {
                        task.Dispatchertime = DateTime.Now;
                    }
                }
                else if (task.TaskType == (int)TaskInboundTypeEnum.Inbound)
                {
                    if (task.TaskState >= (int)TaskInStatusEnum.InFinish)
                    {
                        return content = WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskState}】");
                    }
                    int nextStatus = task.TaskState.GetNextNotCompletedStatus<TaskInStatusEnum>();
                    task.TaskState = nextStatus;
                    if (task.TaskState == (int)TaskInStatusEnum.SC_InExecuting)
                    {
                        task.Dispatchertime = DateTime.Now;
                    }
                    if (task.TaskState == (int)TaskRelocationTypeEnum.Relocation)
                    {
                        Random random = new Random();
                        task.CurrentAddress = task.NextAddress;
                        task.NextAddress = $"{random.Next(1, 100).ToString().PadLeft(3, '0')}-{random.Next(1, 100).ToString().PadLeft(3, '0')}-{random.Next(1, 100).ToString().PadLeft(3, '0')}";
                        task.TargetAddress = task.NextAddress;
                    }
                }
                else if (task.TaskType == (int)TaskInboundTypeEnum.Inbound)
                {
                    if (task.TaskState <= (int)TaskRelocationStatusEnum.SC_RelocationFinish)
                    {
                        return content = WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskState}】");
                    }
                    int nextStatus = (int)TaskRelocationStatusEnum.SC_RelocationExecuting;
                    task.TaskState = nextStatus;
                    if (task.TaskState == (int)TaskRelocationStatusEnum.SC_RelocationExecuting)
                    {
                        task.Dispatchertime = DateTime.Now;
                    }
                }
                else
                {
                    throw new Exception($"任务类型错误,未找到该任务类型,任务号:【{task.TaskNum}】,任务类型:【{task.TaskType}】");
                }
                if (task.TaskState <= 0)
                {
                    return content = WebResponseContent.Instance.Error($"该任务状态不可跳转到下一步,任务号:【{task.TaskNum}】,任务状态:【{task.TaskState}】");
                }
                task.ModifyDate = DateTime.Now;
                task.Modifier = "System";
                BaseDal.UpdateData(task);
                _taskExecuteDetailService.AddTaskExecuteDetail(task.TaskId, App.User.UserId > 0 ? $"人工手动将任务状态从【{oldState}】跳转到【{task.TaskState}】" : $"系统自动流程,任务状态从【{oldState}】转到【{task.TaskState}】");
                content = WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
            {
                content = WebResponseContent.Instance.Error(ex.Message);
            }
            return content;
        }
        /// <summary>
        /// æ ¹æ®ä»»åŠ¡å·ã€å½“å‰åœ°å€æ›´æ–°ä»»åŠ¡ä½ç½®ä¿¡æ¯
        /// </summary>
        /// <param name="taskNum">任务号</param>
        /// <param name="currentAddress">当前地址</param>
        /// <returns></returns>
        public Dt_Task? UpdatePosition(int taskNum, string currentAddress)
        {
            try
            {
                Dt_Task task = BaseDal.QueryFirst(x => x.TaskNum == taskNum && x.CurrentAddress == currentAddress);
                if (task == null) throw new Exception($"未找到该任务信息,任务号:【{taskNum}】");
                string oldCurrentPos = task.CurrentAddress;
                string oldNextPos = task.NextAddress;
                List<Dt_Router> routers = _routerService.QueryNextRoutes(task.NextAddress, task.TargetAddress);
                if (!routers.Any()) throw new Exception($"未找到设备路由信息");
                task.CurrentAddress = task.NextAddress;
                task.NextAddress = routers.FirstOrDefault().ChildPosi;
                task.ModifyDate = DateTime.Now;
                task.Modifier = "System";
                BaseDal.UpdateData(task);
                _taskExecuteDetailService.AddTaskExecuteDetail(task.TaskId, $"系统自动流程,更新当前位置【{oldCurrentPos} ----> {task.CurrentAddress}】和下一位置【{oldNextPos} ----> {task.NextAddress}】");
                return task;
            }
            catch (Exception ex)
            {
            }
            return null;
        }
        public WebResponseContent StackCraneTaskCompleted(int taskNum)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                Dt_Task task = BaseDal.QueryFirst(x => x.TaskNum == taskNum);
                if (task == null) return WebResponseContent.Instance.Error($"未找到该任务信息,任务号:【{taskNum}】");
                if (task.TaskType == (int)TaskOutboundTypeEnum.Outbound && task.TaskState == (int)TaskOutStatusEnum.SC_OutExecuting)
                {
                    /*List<Dt_Router> routers = _routerService.QueryNextRoutes(task.NextAddress, task.TargetAddress);
                    if (!routers.Any()) return WebResponseContent.Instance.Error($"未找到设备路由信息");*/
                    task.TaskState = (int)TaskOutStatusEnum.OutFinish;
                    task.ModifyDate = DateTime.Now;
                    BaseDal.DeleteData(task);
                    _task_HtyService.AddTaskHty(task);
                    _taskExecuteDetailService.AddTaskExecuteDetail(task.TaskId, $"出库完成");
                    //todo åŒæ­¥åˆ°WMS
                    //暂不考虑多个出库口
                }
                else if (task.TaskType == (int)TaskInboundTypeEnum.Inbound && task.TaskState == (int)TaskInStatusEnum.SC_InExecuting)
                {
                    //todo
                    //int nextStatus = task.TaskState.GetNextNotCompletedStatus<TaskInStatusEnum>();
                    task.TaskState = (int)TaskInStatusEnum.InFinish;
                    task.ModifyDate = DateTime.Now;
                    task.Modifier = "System";
                    BaseDal.DeleteData(task);
                    _task_HtyService.AddTaskHty(task);
                    _taskExecuteDetailService.AddTaskExecuteDetail(task.TaskId, $"入库完成");
                }
                else
                {
                    throw new Exception($"任务类型错误,未找到该任务类型,任务号:【{taskNum}】,任务类型:【{task.TaskType}】");
                }
                content = WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
            {
                content = WebResponseContent.Instance.Error($"任务完成异常,任务号:【{taskNum}】");
            }
            return content;
        }
        /// <summary>
        /// æ¢å¤æŒ‚起任务
        /// </summary>
        /// <param name="taskNum">任务号</param>
        /// <returns>返回处理结果</returns>
        public WebResponseContent TaskStatusRecovery(int taskNum)
        {
            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)TaskInStatusEnum.InPending && task.TaskState != (int)TaskOutStatusEnum.OutPending)
                {
                    return content = WebResponseContent.Instance.Error($"该任务状态不可恢复,任务号:【{taskNum}】,任务状态:【{task.TaskState}】");
                }
                Dt_TaskExecuteDetail taskExecuteDetail = _taskExecuteDetailRepository.QueryFirst(x => x.TaskId == task.TaskId && x.IsNormal, new Dictionary<string, OrderByType> { { nameof(Dt_TaskExecuteDetail.TaskDetailId), OrderByType.Desc } });
                if (taskExecuteDetail != null)
                {
                    task.TaskState = taskExecuteDetail.TaskState;
                }
                else
                {
                    if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup)
                    {
                        task.TaskState = (int)TaskOutStatusEnum.OutNew;
                    }
                    else if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.InboundGroup)
                    {
                        task.TaskState = (int)TaskInStatusEnum.InNew;
                    }
                    //todo
                }
                task.ExceptionMessage = string.Empty;
                BaseDal.UpdateData(task);
                _taskExecuteDetailService.AddTaskExecuteDetail(task.TaskId, $"人工恢复挂起任务,恢复挂起时任务状态【{task.TaskState}】");
                content = WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
            {
                content = WebResponseContent.Instance.Error(ex.Message);
            }
            return content;
        }
        /// <summary>
        /// å›žæ»šä»»åŠ¡çŠ¶æ€
        /// </summary>
        /// <param name="taskNum">任务号</param>
        /// <returns>返回处理结果</returns>
        public WebResponseContent RollbackTaskStatusToLast(int taskNum)
        {
            WebResponseContent content = new();
            try
            {
                Dt_Task task = BaseDal.QueryFirst(x => x.TaskNum == taskNum);
                if (task == null) return WebResponseContent.Instance.Error($"未找到该任务信息,任务号:【{taskNum}】");
                int oldState = task.TaskState;
                Dt_TaskExecuteDetail taskExecuteDetail = _taskExecuteDetailRepository.QueryFirst(x => x.TaskId == task.TaskId && x.TaskState < task.TaskState && x.TaskState > 0, new Dictionary<string, OrderByType> { { nameof(Dt_TaskExecuteDetail.TaskDetailId), OrderByType.Desc } });
                if (taskExecuteDetail != null)
                {
                    task.TaskState = taskExecuteDetail.TaskState;
                    task.CurrentAddress = taskExecuteDetail.CurrentAddress;
                    task.NextAddress = taskExecuteDetail.NextAddress;
                }
                else
                {
                    return content = WebResponseContent.Instance.Error($"未找到任务明细信息,该任务状态不可回滚到上一步,任务号:【{taskNum}】,任务状态:【{task.TaskState}】");
                }
                task.ExceptionMessage = string.Empty;
                BaseDal.UpdateData(task);
                _taskExecuteDetailService.AddTaskExecuteDetail(task.TaskId, $"人工将任务状态从【{oldState}】回滚到【{task.TaskState}】");
                content = WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
            {
                content = WebResponseContent.Instance.Error(ex.Message);
            }
            return content;
        }
        /// <summary>
        /// åˆ é™¤æ•°æ®
        /// </summary>
        /// <param name="keys">主键数组</param>
        /// <returns></returns>
        public virtual WebResponseContent DeleteData(object[] keys)
        {
            try
            {
                List<Dt_Task> tasks = BaseDal.QureyDataByIds(keys);
                foreach (Dt_Task task in tasks)
                {
                    _task_HtyService.AddTaskHty(task);
                }
                if (typeof(Dt_Task).GetNavigatePro() == null)
                    return BaseDal.DeleteDataByIds(keys) ? WebResponseContent.Instance.OK() : WebResponseContent.Instance.Error();
                else
                {
                    if (keys != null)
                    {
                        Type detailType = typeof(Dt_Task).GetDetailType();
                        string name = typeof(Dt_Task).GetMainIdByDetail();
                        List<object> dynamicDelKeys = new List<object>();
                        for (int i = 0; i < keys.Length; i++)
                        lock (placedBlocks)
                        {
                            dynamicDelKeys.Add(keys[i]);
                            int length = Convert.ToInt32(orderDetails[i].Orderdetails_length);
                            int width = Convert.ToInt32(orderDetails[i].Orderdetails_width);
                            int height = Convert.ToInt32(orderDetails[i].Orderdetails_thickness);
                            TaskPosition taskPosition = new TaskPosition();
                            taskPosition = GetTakePutPosition(length, width, height, containerSize, placedBlocks);
                            PlacedBlock placedBlock = new PlacedBlock(new Point3D(taskPosition.PositionX, taskPosition.PositionY, taskPosition.PositionZ), length, width, height);
                            placedBlocks.Add(placedBlock);
                            object obj = new
                            {
                                x = taskPosition.PutCenterPositionX - containerSize.Length / 2,
                                y = taskPosition.PutCenterPositionY - containerSize.Width / 2,
                                z = taskPosition.PutCenterPositionZ,
                                length,
                                width,
                                height,
                            };
                            _webSocketServer.PublishAllClientPayload(obj.Serialize());
                            Thread.Sleep(100);
                        }
                        ((SqlSugarClient)BaseDal.Db).BeginTran();
                        if (dynamicDelKeys.Count > 0)
                            BaseDal.Db.Deleteable<object>().AS(detailType.Name).Where($"{name} in (@id)", new { id = dynamicDelKeys.ToArray() }).ExecuteCommandHasChange();
                        BaseDal.DeleteDataByIds(keys);
                        ((SqlSugarClient)BaseDal.Db).CommitTran();
                        return WebResponseContent.Instance.OK();
                    }
                    else
                    catch (Exception ex)
                    {
                        return WebResponseContent.Instance.Error("参数错误");
                    }
                }
                return WebResponseContent.Instance.OK(data: placedBlocks);
            }
            catch (Exception ex)
            {
                ((SqlSugarClient)BaseDal.Db).RollbackTran();
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        //agv任务
        public WebResponseContent GetAgvTaskData()
        public TaskPosition GetTakePutPosition(int length, int width, int height, ContainerSize containerSize, List<PlacedBlock> placedBlocks)
        {
            WebResponseContent content=new WebResponseContent();
            List<Dt_Task> tasks = BaseDal.QueryData().ToList();
            List<AGCTaskDto> agvdto = new List<AGCTaskDto>();
            foreach (var item in tasks)
            {
                AGCTaskDto aGCTaskDto = new AGCTaskDto();
                aGCTaskDto.TaskNum = item.TaskNum;
                aGCTaskDto.SourceAddress= item.SourceAddress;
                aGCTaskDto.TargetAddress= item.TargetAddress==null? "暂定" : item.TargetAddress;
                aGCTaskDto.Dispatchertime = item.Dispatchertime;
                aGCTaskDto.TaskState = item.TaskState == (int)TaskInStatusEnum.InNew ? "新建任务" : (item.TaskState == (int)TaskInStatusEnum.AGV_InExecuting ? "AGV任务执行" : "任务完成");
                aGCTaskDto.TaskType = item.TaskType.ToString();
                aGCTaskDto.Roadway = item.Roadway=="1"?"区域一":(item.Roadway == "2" ? "区域二": item.Roadway == "3" ? "区域三":"区域四");
                agvdto.Add(aGCTaskDto);
            }
            return content.OK(data: agvdto);
        }
        //agv状态
        public WebResponseContent GetAgvStatusData()
        {
            var response = new WebResponseContent();
            try
            {
                //agv类型:0-潜伏型,1 - ç‰µå¼•型,2 - æ‰¿è½½åž‹ï¼Œ3 - ä¸¾å‡åž‹ï¼Œ4 -辊道型,5 - å‰è½¦åž‹ï¼Œ6 - å…¶ä»–
                int agvType = 0;
                //agv编号
                int agvCode = 2;
                //agv上下线状态,0-下线,1 - ä¸Šçº¿
                int agvOnline = 4;
                //agv当前地标号
                int agvRfidLabel = 6;
                //agv当前x坐标值
                int agvXcoordinate = 8;
                //agv当前y坐标值
                int agvYcoordinate = 12;
                //agv运行状态 ï¼š0-停止,1 - è¡Œé©¶ï¼Œ2 - æš‚停
                int agvStatus = 16;
                //agv当前运行速度(mm / s)
                int agvSpeed = 18;
                //agv报警代码(按位状态提取,最多可表示32种报警
                int agvAlarmCode = 20;
                bool isFirst = true;
                List<AGVStatus> statusList = new List<AGVStatus>();
                for (int i = 0; i < 3; i++)
                {
                    AGVStatus aGVStatus = new AGVStatus();
                    aGVStatus.agvCode = i;
                    aGVStatus.agvType = 1+i;
                    aGVStatus.agvOnline = "123" + i;
                    aGVStatus.agvRfidLabel = 2 + i;
                    aGVStatus.agvXcoordinate = 3 + i;
                    aGVStatus.agvYcoordinate = 4 + i;
                    aGVStatus.agvStatus = 5 + i;
                    aGVStatus.agvSpeed = 6 + i;
                    aGVStatus.agvAlarmCode = i+99; //client.SiemensPLCClient.SiemensS7NetClient.Read("DB1001." + agvAlarmCode.ToString(), 32).Content;
                    statusList.Add(aGVStatus);
                PlaceBlockService placeBlockService = new PlaceBlockService(containerSize, placedBlocks);
                Point3D? point3D = placeBlockService.PlaceBlock(length, width, height);
                if (point3D == null)
                {
                    throw new Exception("放货位置已满");
                }
                response.OK(data: statusList);
                //放货位置板材中心点
                Point3D putCenter = new Point3D(point3D.Value.X + length / 2, point3D.Value.Y + width / 2, point3D.Value.Z + height / 2);
                //取货位置板材中心点
                Point3D takeCenter = new Point3D(length / 2, width / 2, height / 2);
                //吸盘长530 é—´éš”660  æœ€å¤§920 å¸ç›˜å®½130
                int positionR = 1;
                int takePositionX = 0;
                int takePositionY = 0;
                int takePositionZ = 0;
                int putPositionX = 0;
                int putPositionY = 0;
                int putPositionZ = 0;
                //1.如果长度大于920,宽度大于等于300,则可以使用双吸盘横向吸取
                if (length > 920 && width >= 300)
                {
                    //
                    Point3D deviceCenter = new Point3D(530 / 2, 920 / 2, 0);
                    positionR = 1;
                    takePositionX = takeCenter.Y - deviceCenter.X;
                    takePositionY = takeCenter.X - deviceCenter.Y;
                    takePositionZ = 10;
                    putPositionX = putCenter.Y - deviceCenter.X;
                    putPositionY = putCenter.X - deviceCenter.Y;
                    putPositionZ = point3D.Value.Z; // putCenter.Z /*+ 10*/;
                }
                else
                {
                    positionR = 0;
                    Point3D deviceCenter = new Point3D(130 / 2, 530 / 2, 0);
                    takePositionX = takeCenter.Y - deviceCenter.X;
                    takePositionY = takeCenter.X - deviceCenter.Y;
                    takePositionZ = 10;
                    putPositionX = putCenter.Y - deviceCenter.X;
                    putPositionY = putCenter.X - deviceCenter.Y;
                    putPositionZ = point3D.Value.Z; //putCenter.Z /*+ 10*/;
                }
                TaskPosition taskPosition = new TaskPosition()
                {
                    PositionR = positionR,
                    TakePositionX = takePositionX,
                    TakePositionY = takePositionY,
                    TakePositionZ = takePositionZ,
                    PutPositionX = putPositionX,
                    PutPositionY = putPositionY,
                    PutPositionZ = putPositionZ,
                    TakeCenterPositionX = takeCenter.X,
                    TakeCenterPositionY = takeCenter.Y,
                    TakeCenterPositionZ = takeCenter.Z,
                    PutCenterPositionX = putCenter.X,
                    PutCenterPositionY = putCenter.Y,
                    PutCenterPositionZ = putCenter.Z,
                    PositionX = point3D.Value.X,
                    PositionY = point3D.Value.Y,
                    PositionZ = point3D.Value.Z
                };
                return taskPosition;
            }
            catch (Exception ex)
            {
                response.Error(ex.Message);
                throw new Exception(ex.Message);
            }
            return response;
        }
        public WebResponseContent GetAgvStatusData2()
        public WebResponseContent CreateTask(string takePosition, string putPosition, string deviceCode, int length, int width, int height)
        {
            var response = new WebResponseContent();
            try
            {
                //agv类型:0-潜伏型,1 - ç‰µå¼•型,2 - æ‰¿è½½åž‹ï¼Œ3 - ä¸¾å‡åž‹ï¼Œ4 -辊道型,5 - å‰è½¦åž‹ï¼Œ6 - å…¶ä»–
                int agvType = 0;
                //agv编号
                int agvCode = 2;
                //agv上下线状态,0-下线,1 - ä¸Šçº¿
                int agvOnline = 4;
                //agv当前地标号
                int agvRfidLabel = 6;
                //agv当前x坐标值
                int agvXcoordinate = 8;
                //agv当前y坐标值
                int agvYcoordinate = 12;
                //agv运行状态 ï¼š0-停止,1 - è¡Œé©¶ï¼Œ2 - æš‚停
                int agvStatus = 16;
                //agv当前运行速度(mm / s)
                int agvSpeed = 18;
                //agv报警代码(按位状态提取,最多可表示32种报警
                int agvAlarmCode = 20;
                bool isFirst = true;
                List<AGVStatus> statusList = new List<AGVStatus>();
                for (int i = 0; i < 6; i++)
                Dt_Container takeContainer = _containerRepository.QueryFirst(x => x.ContainerCode == takePosition && x.ContainerType == ContainerTypeEnum.TakeContainer.ObjToInt());
                if (takeContainer == null)
                {
                    AGVStatus aGVStatus = new AGVStatus();
                    aGVStatus.agvCode = i;
                    aGVStatus.agvType = 1 + i;
                    aGVStatus.agvOnline = "123" + i;
                    aGVStatus.agvRfidLabel = 2 + i;
                    aGVStatus.agvXcoordinate = 3 + i;
                    aGVStatus.agvYcoordinate = 4 + i;
                    aGVStatus.agvStatus = 5 + i;
                    aGVStatus.agvSpeed = 6 + i;
                    aGVStatus.agvAlarmCode = i + 99; //client.SiemensPLCClient.SiemensS7NetClient.Read("DB1001." + agvAlarmCode.ToString(), 32).Content;
                    statusList.Add(aGVStatus);
                    return WebResponseContent.Instance.Error("取货位置不存在");
                }
                response.OK(data: statusList);
                Dt_Container putContainer = _containerRepository.QueryFirst(x => x.ContainerCode == putPosition && x.ContainerType == ContainerTypeEnum.PutContainer.ObjToInt());
                if (putContainer == null)
                {
                    return WebResponseContent.Instance.Error("放货位置不存在");
                }
                ContainerSize containerSize = new ContainerSize(putContainer.ContainerLength, putContainer.ContainerWidth, putContainer.ContainerHeight);
                List<Dt_ContainerItem> containerItems = _containerItemRepository.QueryData(x => x.ContainerId == putContainer.Id);
                List<PlacedBlock> placedBlocks = containerItems.Select(x => new PlacedBlock(new Point3D(x.ItemPositionX, x.ItemPositionY, x.ItemPositionZ), x.ItemLength, x.ItemWidth, x.ItemHeight)).ToList();
                TaskPosition taskPosition = GetTakePutPosition(length, width, height, containerSize, placedBlocks);
                object obj = new
                {
                    x = taskPosition.PutCenterPositionX - putContainer.ContainerLength / 2,
                    y = taskPosition.PutCenterPositionY - putContainer.ContainerWidth / 2,
                    z = taskPosition.PutCenterPositionZ,
                    length,
                    width,
                    height,
                };
                _webSocketServer.PublishAllClientPayload(obj.Serialize());
                string code = DateTime.Now.ToString("yyyyMMddHHmmss");
                Dt_ContainerItem dt_ContainerItem = new Dt_ContainerItem()
                {
                    ContainerId = putContainer.Id,
                    ItemCode = code,
                    ItemLength = length,
                    ItemWidth = width,
                    ItemHeight = height,
                    ItemPositionX = taskPosition.PutPositionX,
                    ItemPositionY = taskPosition.PutPositionY,
                    ItemPositionZ = taskPosition.PutPositionZ,
                    ItemStatus = (int)ItemStatusEnum.Assigned,
                    ItemName = code
                };
                Dt_Task dt_Task = new Dt_Task()
                {
                    TaskNum = 1,
                    PalletCode = code,
                    DeviceCode = deviceCode,
                    TaskState = (int)TaskStatusEnum.Gantry_New,
                    TaskType = 0,
                    SourceAddress = $"{takePosition}*{taskPosition.TakePositionX}*{taskPosition.TakePositionY}*{taskPosition.TakePositionZ}*{taskPosition.PositionR}",
                    TargetAddress = $"{putPosition}*{taskPosition.PutPositionX}*{taskPosition.PutPositionX}*{taskPosition.PutPositionZ}*{taskPosition.PositionR}",
                    CurrentAddress = $"{takePosition}*{taskPosition.TakePositionX}*{taskPosition.TakePositionY}*{taskPosition.TakePositionZ}*{taskPosition.PositionR}",
                    NextAddress = $"{putPosition}*{taskPosition.PutPositionX}*{taskPosition.PutPositionX}*{taskPosition.PutPositionZ}*{taskPosition.PositionR}",
                    Grade = 0,
                };
                _containerItemRepository.AddData(dt_ContainerItem);
                base.AddData(dt_Task);
                return WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
            {
                response.Error(ex.Message);
                return WebResponseContent.Instance.Error(ex.Message);
            }
            return response;
        }
        public class AGVStatus
        {
            /// <summary>
            /// agv类型:0-潜伏型,1 - ç‰µå¼•型,2 - æ‰¿è½½åž‹ï¼Œ3 - ä¸¾å‡åž‹ï¼Œ4 -辊道型,5 - å‰è½¦åž‹ï¼Œ6 - å…¶ä»–
            /// </summary>
            public int agvType { get; set; }
            /// <summary>
            /// agv编号
            /// </summary>
            public int agvCode { get; set; }
            /// <summary>
            /// agv上下线状态,0-下线,1 - ä¸Šçº¿
            /// </summary>
            public string agvOnline { get; set; }
            /// <summary>
            /// agv当前地标号
            /// </summary>
            public int agvRfidLabel { get; set; }
            /// <summary>
            /// agv当前x坐标值
            /// </summary>
            public int agvXcoordinate { get; set; }
            /// <summary>
            /// agv当前y坐标值
            /// </summary>
            public int agvYcoordinate { get; set; }
            /// <summary>
            /// agv运行状态 ï¼š0-停止,1 - è¡Œé©¶ï¼Œ2 - æš‚停
            /// </summary>
            public int agvStatus { get; set; }
            /// <summary>
            /// agv当前运行速度(mm / s)
            /// </summary>
            public int agvSpeed { get; set; }
            /// <summary>
            /// agv报警代码(按位状态提取,最多可表示32种报警
            /// </summary>
            public int agvAlarmCode { get; set; }
        }
    }
}