helongyang
2026-03-31 8fcd7a67e4391a5f1fbdb590c2a3f913aeb2a0a0
PP平库功能上线,PDA优化,部分问题点优化
已添加4个文件
已修改49个文件
3299 ■■■■ 文件已修改
代码管理/WCS/WIDESEAWCS_Client/src/views/Index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/TaskEnum/TaskTypeEnum.cs 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/AGV/PP_AGVController.cs 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/PP仓/AGV_PPExtend.cs 55 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/阻焊仓/AGV_ZHExtend.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSClient/src/extension/basic/extend/materielcodeprintView.vue 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSClient/src/extension/outbound/extend/mesPPCutOutOrderDetail.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSClient/src/extension/outbound/mesPPCutOutboundOrderDetail.js 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSClient/src/extension/outbound/mesPPOutboundOrderDetail.js 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSClient/src/views/basic/locationInfo.vue 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSClient/src/views/basic/materielCodeInfo.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSClient/src/views/outbound/mesPPCutOutboundOrder.vue 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSClient/src/views/outbound/mesPPCutOutboundOrderDetail.vue 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSClient/src/views/outbound/mesPPOutboundOrder.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_BasicRepository/LocationInfoRepository.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/Service/LocationInfoService_Common.cs 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_Common/TaskEnum/TaskTypeEnum.cs 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_Common/WareHouseEnum/WarehouseEnum.cs 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_Core/BaseModels/PageDataOptions.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_Core/CodeConfigEnum/AnalysisCodeEnum.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_Core/CodeConfigEnum/AnalysisFormatTypeEnum.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_Core/Helper/CodeAnalysisHelper.cs 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_DTO/Basic/MatSerNumAnalysisModel.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_IBasicRepository/ILocationInfoRepository.cs 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_IInboundService/IInboundOrderService.cs 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_IOutboundService/IMesPPOutboundOrderService.cs 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutStockLockInfoService.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_IStockService/IStockInfoService.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_ITaskInfoService/ITaskService.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_InboundService/ReceiveOrderService.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_Model/Models/Basic/Dt_MaterielCodeInfo.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_MesPPCutOutboundOrderDetail.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/MesPPCutOutboundOrderDetailService.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/MesPPOutboundOrderService.cs 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/OutStockLockInfoService.cs 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoService.cs 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/MesTaskService.cs 490 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs 77 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Inbound.cs 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Outbound.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Basic/MaterielInfoController.cs 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/MES/MesController.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/TaskInfo/TaskController.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Filter/CustomProfile.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/淮安PDA/pages/stash/PPPKboxing.vue 517 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/淮安PDA/pages/stash/PPTaskMove.vue 727 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/淮安PDA/pages/stash/PPTaskTransport.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/淮安PDA/pages/stash/ProEmptyBack.vue 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/淮安PDA/pages/stash/boxing.vue 63 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
代码管理/淮安PDA/pages/stash/raworderboxing.vue 113 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
´úÂë¹ÜÀí/WCS/WIDESEAWCS_Client/src/views/Index.vue
@@ -322,7 +322,7 @@
      //创建WebSocket连接
      //"ws://127.0.0.1:9295/admin"
      //client = new WebSocket("ws://192.168.0.250:9260/");
      client = new WebSocket("ws:localhost:9260/");
      client = new WebSocket("ws:10.30.4.92:9260/");
      client.onopen = function() {
        //client.onmessage = handleMessage;
        // store.commit("setWebsocket", client);
´úÂë¹ÜÀí/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/TaskEnum/TaskTypeEnum.cs
@@ -55,10 +55,21 @@
        MesOutbound = 200,
        /// <summary>
        /// MES大卷PP出库
        /// </summary>
        [Description("MES大卷PP出库")]
        MesPPOutbound = 205,
        /// <summary>
        /// MES手动出库
        /// </summary>
        [Description("MES手动出库")]
        MesHandOutbound = 210,
        /// <summary>
        /// MES小卷PP出库
        /// </summary>
        [Description("MES小卷PP出库")]
        MesPPCutOutbound = 215,
        /// <summary>
        /// MES手动拣选出库
@@ -108,6 +119,12 @@
        /// </summary>
        [Description("防焊到线边大件")]
        MaskOutLarge = 275,
        /// <summary>
        /// PP搬运至线边
        /// </summary>
        [Description("PP搬运至线边")]
        MesPPMove = 280,
        /// <summary>
        /// é‡‡è´­å…¥åº“
        /// </summary>
@@ -160,6 +177,12 @@
        MesPalletSmallReturn = 585,
        /// <summary>
        /// PP入平库
        /// </summary>
        [Description("PP入平库")]
        PPPKInbound = 590,
        /// <summary>
        /// ç©ºç®±å…¥åº“
        /// </summary>
        [Description("空箱入库")]
´úÂë¹ÜÀí/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/AGV/PP_AGVController.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,101 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using WIDESEA_DTO.Agv;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.Enums;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_IBasicInfoRepository;
using WIDESEAWCS_ITaskInfoRepository;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
using WIDESEAWCS_Tasks;
namespace WIDESEAWCS_Server.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class PP_AGVController : ControllerBase
    {
        private readonly IStationMangerRepository _stationMangerRepository;
        private readonly ITaskService _taskService;
        private readonly ITaskRepository _taskRepository;
        public PP_AGVController(IStationMangerRepository stationMangerRepository, ITaskService taskService, ITaskRepository taskRepository)
        {
            _stationMangerRepository = stationMangerRepository;
            _taskService = taskService;
            _taskRepository = taskRepository;
        }
        /// <summary>
        /// AGV任务更新/完成
        /// </summary>
        /// <param name="agvUpdateModel"></param>
        /// <returns></returns>
        [HttpPost, HttpGet, Route("AgvCallback"), AllowAnonymous]
        public AgvResponseContent AgvUpdateTask([FromBody] AgvUpdateDTO agvUpdateModel)
        {
            AgvResponseContent agvResponseContent = new AgvResponseContent();
            try
            {
                if (agvUpdateModel == null) throw new Exception("未获取到请求参数");
                agvResponseContent.ReqCode = agvUpdateModel.ReqCode;
                var task = _taskRepository.QueryFirst(x => agvUpdateModel.TaskCode == x.AgvTaskNum);
                if (task == null && agvUpdateModel.Method != "begin") throw new Exception($"未找到任务,任务号【{agvUpdateModel.TaskCode}】");
                switch (agvUpdateModel.Method)
                {
                    case "start":
                        break;
                    case "begin":
                        break;
                    case "outbin"://出库根据这个信号判断取货完成
                        if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup)
                        {
                            task.TaskState = TaskStatusEnum.AGV_Finish.ObjToInt();
                            var up = _taskRepository.DeleteAndMoveIntoHty(task, OperateTypeEnum.自动完成);
                            _taskService.TaskCompleted(task.TaskNum);
                            agvResponseContent.Code = up ? "0" : "1";
                            agvResponseContent.Message = up ? "成功" : "失败";
                            return agvResponseContent;
                        }
                        break;
                    case "getSafetySignal"://安全信号申请
                        {
                            break;
                        }
                    case "end"://入库根据这个信号判断放货完成
                        if (task.TaskType != TaskTypeEnum.Outbound.ObjToInt())
                        {
                            task.TaskState = TaskStatusEnum.AGV_Finish.ObjToInt();
                            var up = _taskRepository.DeleteAndMoveIntoHty(task, OperateTypeEnum.自动完成);
                            _taskService.TaskCompleted(task.TaskNum);
                            agvResponseContent.Code = up ? "0" : "1";
                            agvResponseContent.Message = up ? "成功" : "失败";
                            return agvResponseContent;
                        }
                        break;
                    case "cancel":
                        task.TaskState = TaskStatusEnum.Cancel.ObjToInt();
                        _taskRepository.UpdateData(task);
                        break;
                    default:
                        throw new Exception($"未定义方法名【{agvUpdateModel.Method}】");
                }
                agvResponseContent.Code = "0";
                agvResponseContent.Message = "成功";
            }
            catch (Exception ex)
            {
                agvResponseContent.Code = "1";
                agvResponseContent.Message = ex.Message;
            }
            return agvResponseContent;
            //return _taskService.AgvUpdateTask(agvUpdateModel);
        }
    }
}
´úÂë¹ÜÀí/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs
@@ -354,6 +354,13 @@
                        if (taskTypeGroup == TaskTypeGroup.OutbondGroup)
                        {
                            task.AgvTaskNum = item.AGVArea + DateTime.Now.ToString("yyMMdd") + item.TaskNum;
                            if(item.AGVArea == "AGV_PP")
                            {
                                task.NextAddress = item.TargetAddress;
                                task.DeviceCode = item.RoadWay;
                            }
                            else
                            {
                            List<Dt_Router> routers = routersAll.Where(x => x.InOutType == item.TaskType && item.AGVArea == x.NextPosi).ToList();
                            if (routers.FirstOrDefault() == null)
                            {
@@ -370,6 +377,15 @@
                            {
                                task.TaskState = TaskStatusEnum.SC_Execute.ObjToInt();
                            }
                            }
                        }
                        else
                        {
                            if (item.AGVArea == "AGV_PP")
                            {
                                task.AgvTaskNum = item.AGVArea + DateTime.Now.ToString("yyMMdd") + item.TaskNum;
                                task.NextAddress = item.TargetAddress;
                                task.DeviceCode = item.RoadWay;
                        }
                        else
                        {
@@ -400,6 +416,7 @@
                            }
                        }
                    }
                    }
                    tasks.Add(task);
                }
´úÂë¹ÜÀí/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/PP²Ö/AGV_PPExtend.cs
@@ -20,45 +20,70 @@
            try
            {
                var newTasks = _taskService.Db.Queryable<Dt_Task>().Where(x => (x.TaskState == TaskStatusEnum.New.ObjToInt()||x.TaskState==TaskStatusEnum.AGV_Execute.ObjToInt()) && nameof(AGV_PPJob).Contains(x.DeviceCode) && !string.IsNullOrEmpty(x.DeviceCode)).ToList().OrderBy(x => x.Grade).ThenBy(x => x.CreateDate).ToList();
                foreach (var task in newTasks)
                foreach (var agvTask in newTasks)
                {
                    try
                    {
                        AgvTaskDTO TaskDTO = new AgvTaskDTO()
                        string taskTyp;
                        if (agvTask.TaskType == TaskTypeEnum.MesPPMove.ObjToInt())
                        {
                            TaskCode = task.AgvTaskNum,
                            ReqCode = DateTime.Now.ToString("yyMMddHHmmss") + task.AgvTaskNum,
                            TaskTyp = task.TaskType < TaskTypeEnum.Inbound.ObjToInt() ? "FLC" : "FLR",
                            ctnrCode = task.PalletCode,
                            taskTyp = "110";
                        }
                        else if (agvTask.PalletType < 2)
                        {
                            taskTyp = "008";
                        }
                        else
                        {
                            taskTyp = "004";
                        }
                        AgvTaskDTO taskDTO = new AgvTaskDTO()
                        {
                            ReqCode = Guid.NewGuid().ToString().Replace("-", ""),
                            TaskTyp = taskTyp,
                            PositionCodePath = new List<CodePath>()
                        {
                            new CodePath()
                            {
                                type="00",
                                positionCode=task.CurrentAddress
                                    positionCode = agvTask.CurrentAddress
                            },
                            new CodePath()
                            {
                                type="00",
                                positionCode=task.NextAddress
                                    type = (agvTask.TaskType == TaskTypeEnum.PPPKInbound.ObjToInt()||agvTask.TaskType == TaskTypeEnum.MesPPCutOutbound.ObjToInt()) ? "00" : "04",
                                    positionCode = agvTask.NextAddress
                            }
                        },
                            TaskCode = agvTask.AgvTaskNum,
                        };
                        WebResponseContent content = _taskService.AgvSendTask(TaskDTO, APIEnum.Agv_PPSendTask);
                        if (!content.Status) throw new Exception(content.Message);
                        task.TaskState = TaskStatusEnum.AGV_Executing.ObjToInt();
                        WebResponseContent content = _taskService.AgvSendTask(taskDTO);
                        if (content.Status)
                        {
                            agvTask.TaskState = TaskStatusEnum.AGV_Executing.ObjToInt();
                            //agvTask.Remark = content.Data.ObjToString();
                            _taskService.UpdateTask(agvTask, TaskStatusEnum.AGV_Executing);
                        }
                        else
                        {
                            agvTask.TaskState = TaskStatusEnum.Exception.ObjToInt();
                            //agvTask.Remark = content.Data.ObjToString();
                            agvTask.ExceptionMessage = content.Message;
                        }
                    }
                    catch (Exception ex)
                    {
                        task.TaskState = TaskStatusEnum.Exception.ObjToInt();
                        task.ExceptionMessage = ex.Message;
                        agvTask.TaskState = TaskStatusEnum.Exception.ObjToInt();
                        //agvTask.Remark = content.Data.ObjToString();
                        agvTask.ExceptionMessage = ex.Message;
                        WriteError(nameof(AGV_PPJob), ex.Message, ex);
                    }
                }
                _taskService.UpdateData(newTasks);
            }
            catch (Exception ex)
            {
                WriteError(nameof(AGV_FLJob), ex.Message, ex);
                WriteError(nameof(AGV_PPJob), ex.Message, ex);
            }
        }
    }
´úÂë¹ÜÀí/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/×躸²Ö/AGV_ZHExtend.cs
@@ -78,7 +78,7 @@
            }
            catch (Exception ex)
            {
                WriteError(nameof(AGV_FLJob), ex.Message, ex);
                WriteError(nameof(AGV_ZHJob), ex.Message, ex);
            }
        }
        /// <summary>
´úÂë¹ÜÀí/WMS/WIDESEA_WMSClient/src/extension/basic/extend/materielcodeprintView.vue
@@ -7,32 +7,26 @@
      :padding="15"
      title="打印"
    >
      <div
        id="printContent"
        style="display: flex; justify-content: center; align-items: center"
      >
        <div
          style="display: flex; justify-content: center; align-items: center"
        >
      <div id="printContent" style="display: flex; justify-content: center; align-items: center">
        <div style="display: flex; justify-content: center; align-items: center">
          <VueQrcode id="qrcode" :value="Code" :size="200"></VueQrcode>
        </div>
      </div>
      <div id="palletcode">
        <!-- <span
          style="display: flex; justify-content: center; align-items: center"
          >{{ Code }}</span
        > -->
        <span
          style="display: flex; justify-content: center; align-items: center"
        <span style="display: flex; justify-content: center; align-items: center"
          >物料编码:{{ materielCode }}</span
        >
        <!-- decimal有值才显示物料长度,无值则隐藏 -->
        <span
          v-if="isHasMaterielLength"
          style="display: flex; justify-content: center; align-items: center; margin-top: 8px"
          >物料长度:{{ materielLength }}</span
        >
      </div>
      <template #footer>
        <el-button type="primary" size="small" @click="print()">打印</el-button>
        <el-button type="danger" size="small" @click="showDetialBox = false"
          >关闭</el-button
        >
        <el-button type="danger" size="small" @click="showDetialBox = false">关闭</el-button>
      </template>
    </vol-box>
  </div>
@@ -42,7 +36,6 @@
import VolBox from "@/components/basic/VolBox.vue";
import VueQrcode from "vue-qrcode";
import QRCode from "qrcode";
import { da } from "element-plus/es/locales.mjs";
export default {
  components: { VolBox, VueQrcode },
  data() {
@@ -57,62 +50,89 @@
      quantity: "",
      productionDate: "",
      effectiveDate: "",
      materielLength: null, // decimal类型初始化为null,匹配后端数值类型
    };
  },
  computed: {
    // è®¡ç®—属性:统一判断是否有物料长度(decimal有有效数值),模板和逻辑复用
    isHasMaterielLength() {
      return this.materielLength !== null && this.materielLength !== undefined&& this.materielLength !== 0;
    },
  },
  methods: {
    open(row) {
      this.row = row;
      this.showDetialBox = true;
      // æ¯æ¬¡æ‰“开重置所有值,避免缓存
      this.resetForm();
      if (row && row.materielCode) {
        this.materielCode = row.materielCode;
        this.lotNo = row.lotNo;
        this.purchaseOrderNo = row.purchaseOrderNo;
        this.quantity = row.quantity;
        // èµ‹å€¼åŸºç¡€å­—段
        this.materielCode = row.materielCode || "";
        this.lotNo = row.lotNo || "";
        this.purchaseOrderNo = row.purchaseOrderNo || "";
        this.quantity = row.quantity || "";
        this.productionDate = formatDate(row.productionDate);
        this.effectiveDate = formatDate(row.effectiveDate);
        // èµ‹å€¼decimal类型物料长度,直接取后端值(null/undefined/数值都兼容)
        this.materielLength = row.materielLength;
      }
      this.Code =
        "M:" +
        this.materielCode +
        ",BS:" +
        this.lotNo +
        ",DM:" +
        this.productionDate +
        ",DE:" +
        this.effectiveDate +
        ",Q:" +
        this.quantity +
        ",PO:" +
        this.purchaseOrderNo;
      // æ ¸å¿ƒï¼šæ‹¼æŽ¥äºŒç»´ç Code,无长度则完全不出现,ML
      this.Code = this.spliceQrCode();
    },
    // æŠ½ç¦»äºŒç»´ç æ‹¼æŽ¥é€»è¾‘,代码更清晰
    spliceQrCode() {
      // åŸºç¡€å›ºå®šæ‹¼æŽ¥éƒ¨åˆ†
      let baseStr = [
        `M:${this.materielCode}`,
        `BS:${this.lotNo}`,
        `DM:${this.productionDate}`,
        `DE:${this.effectiveDate}`,
        `Q:${this.quantity}`,
        `PO:${this.purchaseOrderNo}`,
      ].join(",");
      // ä»…当有物料长度时,追加,ML:数值;无值则直接返回基础串
      if (this.isHasMaterielLength) {
        baseStr += `,ML:${this.materielLength}`;
      }
      return baseStr;
    },
    print() {
      let printContent = document.getElementById("printContent");
      let palletcode = document.getElementById("palletcode");
      var printWindow = window.open("", "");
      printWindow.document.write(printContent.innerHTML);
      printWindow.document.write(palletcode.innerHTML);
      const printContent = document.getElementById("printContent");
      const palletcode = document.getElementById("palletcode");
      const printWindow = window.open("", "");
      // å®Œå–„打印页面结构,避免样式错乱
      printWindow.document.write(`
        <html>
          <head><meta charset="utf-8"><title>打印</title></head>
          <body style="text-align: center; padding: 20px;">
            ${printContent.innerHTML}
            ${palletcode.innerHTML}
          </body>
        </html>
      `);
      printWindow.document.close();
      printWindow.focus();
      printWindow.print();
      printWindow.close();
    },
    formatDate(dateStr) {
      let date = new Date(dateStr);
      let year = date.getFullYear();
      let month = String(date.getMonth() + 1).padStart(2, "0");
      let day = String(date.getDate()).padStart(2, "0");
      return year + "-" + month + "-" + day;
    // é‡ç½®è¡¨å•,避免多次打开弹窗缓存上一次数据
    resetForm() {
      this.materielCode = "";
      this.lotNo = "";
      this.purchaseOrderNo = "";
      this.quantity = "";
      this.productionDate = "";
      this.effectiveDate = "";
      this.materielLength = null;
      this.Code = "";
    },
  },
  created() {},
};
// æ—¥æœŸæ ¼å¼åŒ–工具函数,加空值判断避免报错
function formatDate(dateStr) {
  if (!dateStr) return "";
  const date = new Date(dateStr);
  return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(
    2,
    "0"
  )}-${String(date.getDate()).padStart(2, "0")}`;
  return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
}
</script>
  
@@ -120,39 +140,41 @@
.el-col {
  border-radius: 4px;
}
.grid-content {
  border-radius: 4px;
  min-height: 36px;
}
.content-text {
  display: flex;
  align-items: center;
  justify-content: center;
}
.right-text {
  display: flex;
  align-items: center;
  justify-content: flex-end;
}
</style>
  <style>
.el-table .warning-row {
  background: #e6a23c;
}
.el-table .success-row {
  background: #f0f9eb;
}
.el-table .error-row {
  background: #f56c6c;
}
canvas {
  display: block;
  margin: auto;
}
/* æ‰“印样式优化,适配打印机 */
@media print {
  body {
    margin: 0;
    padding: 0;
  }
}
</style>
´úÂë¹ÜÀí/WMS/WIDESEA_WMSClient/src/extension/outbound/extend/mesPPCutOutOrderDetail.vue
@@ -129,30 +129,28 @@
          hidden: true,
        },
        {
          prop: "materielCode",
          prop: "materialCode",
          title: "物料编号",
          type: "string",
          width: 150,
        },
        {
          prop: "materielName",
          prop: "materialName",
          title: "物料名称",
          type: "string",
          width: 150,
        },
      {
        field: "targetAddressCode",
        prop: "targetAddressCode",
        title: "线边仓地址码",
        type: "string",
        width: 100,
        align: "left",
      },
      {
        field: "width",
        prop: "width",
        title: "裁切宽",
        type: "string",
        width: 100,
        align: "left",
      },
        {
          prop: "orderQuantity",
´úÂë¹ÜÀí/WMS/WIDESEA_WMSClient/src/extension/outbound/mesPPCutOutboundOrderDetail.js
@@ -4,7 +4,7 @@
    components: {
      //查询界面扩展组件
      gridHeader: '',
      gridBody: gridBody,
      gridBody: '',
      gridFooter: '',
      //新建、编辑弹出框扩展组件
      modelHeader: '',
@@ -17,21 +17,7 @@
       //下面这些方法可以保留也可以删除
      onInit() {  
        //扩展页面初始化操作
        this.columns.push({
          field: '操作',
          title: '操作',
          width: 90,
          fixed: 'right',
          align: 'center',
          formatter: (row) => {
              return (
                  '<i style="cursor: pointer;color: #2d8cf0;"class="el-icon-view">查看明细</i>'
              );
          },
          click: (row) => {
              this.$refs.gridBody.open(row);
          }
      });
      },
      onInited() {
        //框架初始化配置后
´úÂë¹ÜÀí/WMS/WIDESEA_WMSClient/src/extension/outbound/mesPPOutboundOrderDetail.js
@@ -4,7 +4,7 @@
  components: {
    //查询界面扩展组件
    gridHeader: '',
    gridBody: gridBody,
    gridBody: '',
    gridFooter: '',
    //新建、编辑弹出框扩展组件
    modelHeader: '',
@@ -17,21 +17,7 @@
     //下面这些方法可以保留也可以删除
    onInit() {  
      //扩展页面初始化操作
      this.columns.push({
        field: '操作',
        title: '操作',
        width: 90,
        fixed: 'right',
        align: 'center',
        formatter: (row) => {
            return (
                '<i style="cursor: pointer;color: #2d8cf0;"class="el-icon-view">查看明细</i>'
            );
        },
        click: (row) => {
            this.$refs.gridBody.open(row);
        }
    });
    },
    onInited() {
      //框架初始化配置后
´úÂë¹ÜÀí/WMS/WIDESEA_WMSClient/src/views/basic/locationInfo.vue
@@ -40,9 +40,6 @@
      locationType: "",
      enableStatus: "",
      locationStatus: "",
      row: "",
      column: "",
      layer: "",
    });
    const searchFormOptions = ref([
      [
@@ -109,7 +106,7 @@
      {
        field: "column",
        title: "货位列",
        type: "int",
        type: "string",
        width: 120,
        align: "left",
        hidden: true,
´úÂë¹ÜÀí/WMS/WIDESEA_WMSClient/src/views/basic/materielCodeInfo.vue
@@ -105,6 +105,8 @@
      [
        { title: "采购单号", field: "purchaseOrderNo", type: "like" },
        { title: "物料编号", field: "materielCode", type: "like" },
        {title: "所属仓库", field:"warehouseId",type:"select",dataKey:"warehouses",data:[]},
        { title: "批次号", field: "lotNo", type: "like" },
      ],
    ]);
    const columns = ref([
@@ -176,6 +178,13 @@
        align: "left",
      },
      {
        field: "materielLength",
        title: "物料长度",
        type: "int",
        width: 80,
        align: "left",
      },
      {
        field: "productionDate",
        title: "生产日期",
        type: "date",
´úÂë¹ÜÀí/WMS/WIDESEA_WMSClient/src/views/outbound/mesPPCutOutboundOrder.vue
@@ -85,6 +85,7 @@
    const searchFormOptions = ref([
      [
        { title: "单据编号", field: "orderNo", type: "like" },
        { title: "上游单据编号", field: "taskNo", type: "like" },
        {
          title: "单据类型",
          field: "orderType",
@@ -134,6 +135,14 @@
      {
        field: "orderNo",
        title: "单据编号",
        type: "string",
        width: 160,
        align: "left",
        // link: true
      },
      {
        field: "taskNo",
        title: "上游单据编号",
        type: "string",
        width: 160,
        align: "left",
@@ -214,14 +223,14 @@
        hidden: true,
      },
      {
        field: "materielCode",
        field: "materialCode",
        title: "物料编号",
        type: "string",
        width: 150,
        align: "left",
      },
      {
        field: "materielName",
        field: "materialName",
        title: "物料名称",
        type: "string",
        width: 150,
´úÂë¹ÜÀí/WMS/WIDESEA_WMSClient/src/views/outbound/mesPPCutOutboundOrderDetail.vue
@@ -27,14 +27,7 @@
      sortName: "id",
    });
    const editFormFields = ref({
      deviceCode: "",
      deviceName: "",
      deviceType: "",
      deviceStatus: "",
      deviceIp: "",
      devicePort: "",
      devicePlcType: "",
      deviceRemark: "",
    });
    const editFormOptions = ref([
      [
@@ -63,37 +56,23 @@
          type: "string",
        },
      ],
      [
        { title: "设备IP", required: true, field: "deviceIp", type: "string" },
        {
          title: "设备端口",
          required: true,
          field: "devicePort",
          type: "string",
        },
        {
          title: "PLC类型",
          required: true,
          field: "devicePlcType",
          type: "string",
        },
        {
          title: "备注",
          field: "deviceRemark",
          type: "string",
        },
      ],
    ]);
    const searchFormFields = ref({
      deviceCode: "",
      deviceType: "",
      deviceStatus: "",
    });
    const searchFormOptions = ref([
      [
        { title: "设备编号", field: "deviceCode" },
        { title: "设备类型", field: "deviceType" },
        { title: "设备状态", field: "deviceStatus" },
        { title: "物料名称", field: "materialName", type: "like" },
        { title: "物料编号", field: "materialCode", type: "like" },
        { title: "批次号", field: "batchNo", type: "like" },
        {
          title: "单据明细状态",
          field: "orderDetailStatus",
          type: "select",
          dataKey: "orderDetailStatusEnum",
          data: [],
        },
      ],
    ]);
    const columns = ref([
@@ -115,14 +94,14 @@
        hidden: true,
      },
      {
        field: "materielCode",
        field: "materialCode",
        title: "物料编号",
        type: "string",
        width: 150,
        align: "left",
      },
      {
        field: "materielName",
        field: "materialName",
        title: "物料名称",
        type: "string",
        width: 150,
@@ -180,9 +159,10 @@
      {
        field: "orderDetailStatus",
        title: "订单明细状态",
        type: "string",
        type: "select",
        width: 180,
        align: "left",
        bind: { key: "orderDetailStatusEnum", data: [] },
      },
      {
        field: "LayerCode",
@@ -235,7 +215,7 @@
      },
    ]);
    const detail = ref({
      cnName: "#detailCnName",
        cnName: "MES出库单明细",
      table: "",
      columns: [],
      sortName: "",
´úÂë¹ÜÀí/WMS/WIDESEA_WMSClient/src/views/outbound/mesPPOutboundOrder.vue
@@ -36,8 +36,18 @@
    const searchFormOptions = ref([
      [
        { title: "单据编号", field: "orderNo", type: "like" },
        { title: "任务单号", field: "taskNo", type: "like" },
        { title: "物料编号", field: "materialCode", type: "like" },
        { title: "批次号", field: "batchNo", type: "like" },
      ],
      [
        {
          title: "单据状态",
          field: "orderStatus",
          type: "select",
          dataKey: "orderDetailStatusEnum",
          data: [],
        },
      ],
    ]);
    const columns = ref([
@@ -85,7 +95,7 @@
        type: "decimal",
        width: 90,
        align: "left",
        bind: { key: "outboundStatusEnum", data: [] },
        bind: { key: "orderDetailStatusEnum", data: [] },
      },
      {
        field: "materialCode",
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_BasicRepository/LocationInfoRepository.cs
@@ -5,6 +5,7 @@
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.WareHouseEnum;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.Enums;
using WIDESEA_Core.Helper;
@@ -84,6 +85,17 @@
        {
            return QueryData(x => x.LocationCode, x => x.WarehouseId == warehouseId && x.LocationStatus == LocationStatusEnum.InStock.ObjToInt() && (x.EnableStatus == EnableStatusEnum.OnlyOut.ObjToInt() || x.EnableStatus == EnableStatusEnum.Normal.ObjToInt())).Distinct().ToList();
        }
        /// <summary>
        /// PP大卷出库,平库优先,立库补偿出库的货位编号集合
        /// </summary>
        /// <param name="warehouseId"></param>
        /// <returns></returns>
        public List<string> GetCanOutPPLocationCodes(int warehouseId)
        {
            //查平库货位
            Dt_Warehouse warehouse = Db.Queryable<Dt_Warehouse>().Where(x => x.WarehouseCode == WarehouseEnum.HA581.ToString()).First();
            return QueryData(x => x.LocationCode, x => (x.WarehouseId == warehouseId || x.WarehouseId == warehouse.WarehouseId) && x.LocationStatus == LocationStatusEnum.InStock.ObjToInt() && (x.EnableStatus == EnableStatusEnum.OnlyOut.ObjToInt() || x.EnableStatus == EnableStatusEnum.Normal.ObjToInt())).Distinct().ToList();
        }
        /// <summary>
        /// èŽ·å–å¯å‡ºåº“è´§ä½ç¼–å·
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/Service/LocationInfoService_Common.cs
@@ -59,6 +59,7 @@
                "HA153" => AssignLocation(roadwayNo),
                "HA71" or "HA72" or "HA73" => AssignLocation(roadwayNo),
                "HA60" => AssignLocation(roadwayNo),
                "HA581" => AssignLocation_PPPK(roadwayNo,palletTypeInfo.PalletType),
                _ => throw new Exception($"未找到仓库货位分配方法")
            };
        }
@@ -675,6 +676,34 @@
            }
            return groupLocations;
        }
        public Dt_LocationInfo? AssignLocation_PPPK(string roadwayNo, int palletType)
        {
            lock (_locker)
            {
                List<LocationCache> removeItems = locationCaches.Where(x => (DateTime.Now - x.DateTime).TotalMinutes > 5).ToList();//查询添加静态变量超过5分钟的货位
                int count = removeItems.Count;
                for (int i = 0; i < count; i++)
                {
                    locationCaches.Remove(removeItems[i]);//移除查询添加静态变量超过5分钟的货位
                }
                List<string> lockLocations = locationCaches.Select(x => x.LocationCode).ToList();
                List<Dt_LocationInfo> locationInfos = BaseDal.QueryData(x => x.RoadwayNo == roadwayNo);//查询巷道所有货位信息
                Dictionary<string, OrderByType> orderBy = new Dictionary<string, OrderByType>()
                {
                    { nameof(Dt_LocationInfo.Layer),OrderByType.Asc },
                    { nameof(Dt_LocationInfo.Column),OrderByType.Asc },
                    { nameof(Dt_LocationInfo.Depth),OrderByType.Desc },
                    { nameof(Dt_LocationInfo.Row),OrderByType.Asc }
                };
                return BaseDal.QueryFirst(x => x.RoadwayNo == roadwayNo && x.LocationStatus == LocationStatusEnum.Free.ObjToInt() && x.EnableStatus != EnableStatusEnum.Disable.ObjToInt() && x.LocationType == palletType && !lockLocations.Contains(x.LocationCode), orderBy);
            }
        }
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_Common/TaskEnum/TaskTypeEnum.cs
@@ -63,10 +63,23 @@
        MesOutbound = 200,
        /// <summary>
        /// MES大卷PP出库
        /// </summary>
        [Description("MES大卷PP出库")]
        MesPPOutbound = 205,
        /// <summary>
        /// MES手动出库
        /// </summary>
        [Description("MES手动出库")]
        MesHandOutbound = 210,
        /// <summary>
        /// MES小卷PP出库
        /// </summary>
        [Description("MES小卷PP出库")]
        MesPPCutOutbound = 215,
        /// <summary>
        /// MES手动拣选出库
@@ -116,6 +129,13 @@
        /// </summary>
        [Description("防焊到线边大件")]
        MaskOutLarge = 275,
        /// <summary>
        /// PP搬运至线边
        /// </summary>
        [Description("PP搬运至线边")]
        MesPPMove = 280,
        /// <summary>
        /// é‡‡è´­å…¥åº“
        /// </summary>
@@ -168,6 +188,12 @@
        MesPalletSmallReturn = 585,
        /// <summary>
        /// PP入平库
        /// </summary>
        [Description("PP入平库")]
        PPPKInbound = 590,
        /// <summary>
        /// ç©ºç®±å…¥åº“
        /// </summary>
        [Description("空箱入库")]
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_Common/WareHouseEnum/WarehouseEnum.cs
@@ -76,7 +76,12 @@
        /// é˜»ç„Šä»“
        /// </summary>
        [Description("阻焊仓")]
        HA154
        HA154,
        /// <summary>
        /// PP平库
        /// </summary>
        [Description("PP平库")]
        HA581
    }
    public enum WarehouseTypEnum
    {
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_Core/BaseModels/PageDataOptions.cs
@@ -75,7 +75,7 @@
                    LinqExpressionType expressionType = searchParametersList[i].DisplayType.GetLinqCondition();
                    if (expressionType == LinqExpressionType.Equal)
                    {
                        where += $"{searchParametersList[i].Name} {HtmlElementType.Equal} '{results[j].Item3}'";
                        where += $"[{searchParametersList[i].Name}] {HtmlElementType.Equal} '{results[j].Item3}'";
                    }
                    else if (expressionType == LinqExpressionType.ThanOrEqual)
                    {
@@ -95,7 +95,7 @@
                    }
                    else if (expressionType == LinqExpressionType.Contains)
                    {
                        where += $"{searchParametersList[i].Name} {HtmlElementType.like} '%{searchParametersList[i].Value}%'";
                        where += $"[{searchParametersList[i].Name}] {HtmlElementType.like} '%{searchParametersList[i].Value}%'";
                    }
                    else
                    {
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_Core/CodeConfigEnum/AnalysisCodeEnum.cs
@@ -25,6 +25,7 @@
        OutterCode,
        MatSerNumAnalysis,
        ProSerNumAnalysis
        ProSerNumAnalysis,
        PPPKSerNumAnalysis
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_Core/CodeConfigEnum/AnalysisFormatTypeEnum.cs
@@ -62,5 +62,11 @@
        /// </summary>
        [Description("原始数据")]
        BD,
        /// <summary>
        /// ç‰©æ–™é•¿åº¦
        /// </summary>
        [Description("物料长度")]
        ML,
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_Core/Helper/CodeAnalysisHelper.cs
@@ -200,5 +200,91 @@
            }
            return list;
        }
        public static T PPPKCodeAnalysis<T>(AnalysisCodeEnum analysisCode, string code)
        {
            Type type = typeof(T);
            object? obj = Activator.CreateInstance(type);
            if (obj == null)
                throw new Exception("实例化对象错误");
            T result = (T)obj;
            try
            {
                AnalysisRuleAttribute? analysisRule = type.GetCustomAttribute<AnalysisRuleAttribute>();
                if (analysisRule != null)
                {
                    SqlSugarClient sugarClient = new SqlSugarClient(new ConnectionConfig
                    {
                        ConfigId = MainDb.CurrentDbConnId,
                        ConnectionString = DBContext.GetMainConnectionDb().Connection,
                        IsAutoCloseConnection = true,
                        DbType = MainDb.DbType,
                    });
                    dynamic ruleConfig = sugarClient.Queryable(MainDb.AnalysisRuleConfig, "x").Where(MainDb.AnalysisCode, "=", analysisCode.ToString()).First();
                    if (ruleConfig != null)
                    {
                        string format = ruleConfig.Format;
                        string splitStr = ruleConfig.SplitStr;
                        List<string> items = format.Split(splitStr).ToList();
                        List<string> codes = code.Split(splitStr).ToList();
                        if (items.Count == codes.Count)
                        {
                            PropertyInfo[] propertyInfos = type.GetProperties();
                            if (AnalysisRuleEnum.Split == analysisRule.AnalysisRule)
                            {
                                for (int i = 0; i < propertyInfos.Length; i++)
                                {
                                    PropertyInfo propertyInfo = propertyInfos[i];
                                    AnalysisItemRuleAttribute? analysisItemRule = propertyInfo.GetCustomAttribute<AnalysisItemRuleAttribute>();
                                    if (analysisItemRule != null)
                                    {
                                        if (analysisItemRule.AnalysisFormaType == AnalysisFormatTypeEnum.BD)
                                        {
                                            propertyInfo.SetValue(result, code.ChangeType(propertyInfo.PropertyType));
                                        }
                                        else
                                        {
                                            int index = items.IndexOf($"[{analysisItemRule.AnalysisFormaType}]");
                                            if (index != -1)
                                            {
                                                propertyInfo.SetValue(result, codes[index]);
                                            }
                                            else
                                            {
                                                string? codeItem = items.FirstOrDefault(x => x.Contains($"[{analysisItemRule.AnalysisFormaType}]"));
                                                if (!string.IsNullOrEmpty(codeItem))
                                                {
                                                    index = items.IndexOf(codeItem);
                                                    if (index != -1)
                                                    {
                                                        string value = codes[index];
                                                        string replaceStr = codeItem.Replace($"[{analysisItemRule.AnalysisFormaType}]", "");
                                                        propertyInfo.SetValue(result, value.Replace(replaceStr, "").ChangeType(propertyInfo.PropertyType));
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"解析错误,{ex.Message}");
            }
            (bool, string, object?) validateResult = ModelValidate.ValidateModelData(result, type);
            if (!validateResult.Item1)
            {
                throw new Exception($"解析错误,{validateResult.Item2}");
            }
            return result;
        }
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_DTO/Basic/MatSerNumAnalysisModel.cs
@@ -55,5 +55,11 @@
        /// </summary>
        [AnalysisItemRule(AnalysisFormatTypeEnum.BD), PropertyValidate("原始数据", NotNullAndEmpty = true)]
        public string SerialNumber { get; set; }
        /// <summary>
        /// ç‰©æ–™é•¿åº¦
        /// </summary>
        [AnalysisItemRule(AnalysisFormatTypeEnum.ML), PropertyValidate("原始数据", NotNullAndEmpty = false)]
        public string MaterielLength { get; set; }
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_IBasicRepository/ILocationInfoRepository.cs
@@ -53,6 +53,9 @@
        /// <returns></returns>
        List<string> GetCanOutLocationCodes(int warehouseId);
        List<string> GetCanOutPPLocationCodes(int warehouseId);
        List<string> PPGetCanOutLocationCodes(int warehouseId);
        /// <summary>
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_IInboundService/IInboundOrderService.cs
@@ -53,5 +53,14 @@
        /// æˆå“å…¥åº“上传ERP
        /// </summary>
        WebResponseContent FeedbackProIn(Dt_MesProInOrder mesProInOrder);
        /// <summary>
        /// PP平库组盘
        /// </summary>
        /// <param name="palletCode"></param>
        /// <param name="Initiallife"></param>
        /// <param name="warehouseId"></param>
        /// <param name="serNums"></param>
        /// <returns></returns>
        WebResponseContent PPPKMaterielGroup(string palletCode, int Initiallife, int warehouseId, List<string> serNums);
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_IOutboundService/IMesPPOutboundOrderService.cs
@@ -17,5 +17,8 @@
        //(List<Dt_StockInfo>, Dt_MesPPCutOutboundOrderDetail, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) AssignStockOutbound(Dt_MesPPCutOutboundOrder mesPPOutboundOrder, Dt_MesPPCutOutboundOrderDetail  mesPPCutOutboundOrderDetail);
  
        public (List<Dt_StockInfo>, Dt_MesPPOutboundOrder, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) AssignPPStockOutbound(Dt_MesPPOutboundOrder mesPPOutboundOrder);
        public (List<Dt_StockInfo>, List<Dt_MesPPCutOutboundOrderDetail>, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) AssignPPCutStockOutbound(Dt_MesPPCutOutboundOrder mesPPCutOutboundOrder, List<Dt_MesPPCutOutboundOrderDetail> mesPPCutOutboundOrderDetails);
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutStockLockInfoService.cs
@@ -58,8 +58,10 @@
        /// <param name="assignQuantity"></param>
        /// <param name="taskNum"></param>
        /// <returns></returns>
        List<Dt_OutStockLockInfo> GetOutStockLockInfos(Dt_MesPPCutOutboundOrder mesPPCutOutboundOrder,Dt_MesPPCutOutboundOrderDetail  mesPPCutOutboundOrderDetail, List<Dt_StockInfo> outStock, int? taskNum = null);
        Dt_OutStockLockInfo GetOutStockLockInfos(Dt_MesPPCutOutboundOrder mesPPCutOutboundOrder,Dt_MesPPCutOutboundOrderDetail  mesPPCutOutboundOrderDetail, Dt_StockInfo outStock, int? taskNum = null);
        List<Dt_OutStockLockInfo> GetOutStockLockInfos(Dt_MesPPCutOutboundOrder mesPPCutOutboundOrder, Dt_MesPPCutOutboundOrderDetail mesPPCutOutboundOrderDetail, List<Dt_StockInfo> outStock, int? taskNum = null);
        /// <summary>
        /// 
        /// </summary>
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_IStockService/IStockInfoService.cs
@@ -20,8 +20,12 @@
        List<Dt_StockInfo> GetOutboundStocks(List<Dt_StockInfo> stockInfos, string materielCode, float needQuantity, out float residueQuantity);
        List<Dt_StockInfo> GetOutboundPPStocks(List<Dt_StockInfo> stockInfos, string materielCode, float needQuantity, out float residueQuantity,string targetAddressCode = "");
        List<Dt_StockInfo> GetUseableStocks(string materielCode, string batchNo, int warehoseId);
        List<Dt_StockInfo> GetUseablePPStocks(string materielCode, string batchNo, int warehoseId);
        //List<Dt_StockInfo> GetUseableStocks(string materielCode, string batchNo,,string , int warehoseId);
        List<Dt_StockInfo> GetUseableStocks(string materielCode, string batchNo, string palletcode, int warehoseId);
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_ITaskInfoService/ITaskService.cs
@@ -405,5 +405,21 @@
        /// <param name="warehouseId"></param>
        /// <returns></returns>
        public Task<WebResponseContent> TaskHandCancel(int taskNum);
        /// <summary>
        /// PP平库申请入库任务
        /// </summary>
        /// <param name="palletCode">托盘号</param>
        /// <param name="stationCode">站台号</param>
        /// <returns></returns>
        WebResponseContent PPPKRequestInboundTask(SaveModel saveModel);
        /// <summary>
        /// PP平库生成搬运任务
        /// </summary>
        /// <param name="palletCode">托盘号</param>
        /// <param name="stationCode">站台号</param>
        /// <returns></returns>
        public WebResponseContent PPTaskMove(string palletCode, string startPoint, int warehouseId, List<string> serNums);
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs
@@ -1853,6 +1853,15 @@
            {
                return 4;
            }
            else if (warehouse.WarehouseCode == WarehouseEnum.HA581.ObjToString())
            {
                Dt_PalletTypeInfo palletTypeInfo = _palletTypeInfoRepository.QueryFirst(x => x.CodeStartStr == palletCode.Substring(0, 2));
                if (palletTypeInfo == null)
                {
                    throw new Exception($"托盘号错误");
                }
                return palletTypeInfo.PalletType;
            }
            return -1;
        }
        /// <summary>
@@ -1900,5 +1909,143 @@
            }
            return WebResponseContent.Instance.OK();
        }
        public WebResponseContent PPPKMaterielGroup(string palletCode, int Initiallife, int warehouseId, List<string> serNums)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                Dt_Warehouse warehouse = _warehouseService.Repository.QueryFirst(x => x.WarehouseId == warehouseId);
                if (warehouse == null)
                {
                    return WebResponseContent.Instance.Error($"未找到该仓库信息");
                }
                List<MatSerNumAnalysisModel> models = CodeAnalysisHelper.CodeAnalysis<MatSerNumAnalysisModel>(AnalysisCodeEnum.PPPKSerNumAnalysis, serNums);
                if (models.Select(x => x.MaterielCode).Distinct().Count() > 1)
                {
                    return WebResponseContent.Instance.Error($"物料不可混放");
                }
                //验证判断时间格式
                WebResponseContent IsValidContent = IsValidMCDates(models);
                if (!IsValidContent.Status)
                {
                    return content.Error(IsValidContent.Message);
                }
                string materielCode = models.FirstOrDefault()?.MaterielCode ?? "";
                int materielWidth = 0;
                if (materielCode.Contains("-"))
                {
                    var model = models.FirstOrDefault();
                    if (model != null && !string.IsNullOrEmpty(model.MaterielCode))
                    {
                        var codeParts = model.MaterielCode.Split("-");
                        if (codeParts.Length >= 2)
                        {
                            if (int.TryParse(codeParts[1], out int widthValue))
                            {
                                materielWidth = widthValue;
                            }
                            else
                            {
                                materielWidth = 0;
                            }
                            materielCode = codeParts[0];
                        }
                    }
                }
                Dt_MaterielInfo materielInfo = _basicRepository.MaterielInfoRepository.QueryFirst(x => x.MaterielCode == materielCode);
                if (materielInfo == null)
                {
                    return WebResponseContent.Instance.Error($"未找到该物料的信息");
                }
                float beforeQuantity = 0;
                Dt_StockInfo stockInfo = _stockRepository.StockInfoRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == palletCode).Includes(x => x.Details).First();
                if (stockInfo == null)
                {
                    stockInfo = new Dt_StockInfo()
                    {
                        PalletCode = palletCode,
                        StockStatus = StockStatusEmun.手动组盘暂存.ObjToInt(),
                        WarehouseId = warehouse.WarehouseId,
                        PalletType = GetPalletType(warehouse, palletCode),
                        Details = new List<Dt_StockInfoDetail>()
                    };
                }
                else
                {
                    if (stockInfo.StockStatus != StockStatusEmun.组盘暂存.ObjToInt() && stockInfo.StockStatus != StockStatusEmun.手动组盘暂存.ObjToInt())
                    {
                        return WebResponseContent.Instance.Error($"托盘号重复");
                    }
                    beforeQuantity = stockInfo.Details.Sum(x => x.StockQuantity);
                }
                if(materielWidth != 0&& materielWidth < 650 && stockInfo.PalletType > 1)
                {
                    return WebResponseContent.Instance.Error("低于650裁切宽的物料请用小托盘条码重新组盘!");
                }
                else if(materielWidth != 0 && materielWidth >= 650 && stockInfo.PalletType < 2)
                {
                    return WebResponseContent.Instance.Error("650裁切宽以上的物料请用大托盘条码重新组盘!");
                }
                List<Dt_StockInfoDetail> stockInfoDetails = new List<Dt_StockInfoDetail>();
                List<int> detailKeys = new List<int>();
                foreach (var model in models)
                {
                    Dt_StockInfoDetail stockInfoDetail = new Dt_StockInfoDetail()
                    {
                        BatchNo = model.LotNo,
                        MaterielCode = model.MaterielCode,
                        MaterielName = materielInfo.MaterielName,
                        MaterielSpec = materielInfo.MaterielSpec,
                        OrderNo = "",
                        SerialNumber = model.SerialNumber,
                        StockQuantity = model.MaterielCode.Contains("-")? model.MaterielLength.ObjToInt():model.Quantity,
                        OutboundQuantity = 0,
                        Unit = materielInfo.MaterielUnit,
                        Status = StockStatusEmun.组盘暂存.ObjToInt(),
                        ProductionDate = model.ProductionDate,
                        EffectiveDate = model.EffectiveDate,
                        InboundOrderRowNo = 0,
                    };
                    if (stockInfo.Id > 0)
                    {
                        stockInfoDetail.StockId = stockInfo.Id;
                    }
                    stockInfo.Details.Add(stockInfoDetail);
                    stockInfoDetails.Add(stockInfoDetail);
                }
                float totalQuantity = stockInfo.Details.Sum(x => x.StockQuantity);
                _unitOfWorkManage.BeginTran();
                if (stockInfo.Id == 0)
                {
                    _stockRepository.StockInfoRepository.Db.InsertNav(stockInfo).Include(x => x.Details).ExecuteCommand();
                }
                else
                {
                    _stockRepository.StockInfoRepository.Db.UpdateNav(stockInfo).Include(x => x.Details, new UpdateNavOptions() { OneToManyInsertOrUpdate = true }).ExecuteCommand();
                }
                _recordService.StockQuantityChangeRecordService.AddStockChangeRecord(stockInfo, stockInfoDetails, beforeQuantity, totalQuantity, StockChangeTypeEnum.MaterielGroup);
                _unitOfWorkManage.CommitTran();
                content.OK();
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                content.Error(ex.Message);
            }
            return content;
        }
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_InboundService/ReceiveOrderService.cs
@@ -295,6 +295,10 @@
                        {
                            throw new Exception(mesResponseContent.StrMsg);
                        }
                        if (mesResponseContent.Content == null)
                        {
                            throw new Exception("QMS返回检验结果为空");
                        }
                        //QMS回传结果
                        ReceiveResultDTO? receiveResult = JsonConvert.DeserializeObject<ReceiveResultDTO>(mesResponseContent.Content.ToString());
                        if (receiveResult == null)
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_Model/Models/Basic/Dt_MaterielCodeInfo.cs
@@ -84,5 +84,11 @@
        /// </summary>
        [SugarColumn(IsNullable = false,Length =500,ColumnDescription = "物料规格")]
        public string MaterielSpec { get; set; }
        /// <summary>
        /// ç‰©æ–™é•¿åº¦
        /// </summary>
        [SugarColumn(IsNullable = true, ColumnDescription = "物料长度")]
        public decimal MaterielLength { get; set; }
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_Model/Models/Outbound/Dt_MesPPCutOutboundOrderDetail.cs
@@ -30,13 +30,13 @@
        /// ç‰©æ–™ç¼–号
        /// </summary>
        [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "物料编号")]
        public string MaterielCode { get; set; }
        public string MaterialCode { get; set; }
        /// <summary>
        /// ç‰©æ–™åç§°
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 200, ColumnDescription = "物料名称")]
        public string MaterielName { get; set; }
        public string MaterialName { get; set; }
        /// <summary>
        /// æ‰¹æ¬¡å·
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/MesPPCutOutboundOrderDetailService.cs
@@ -133,9 +133,9 @@
            needQuantity -= assignQuantity;
            if (mesPPOutboundOrderDetails.OrderQuantity > mesPPOutboundOrderDetails.LockQuantity)
            {
                List<Dt_StockInfo> stockInfos = _stockService.StockInfoService.GetUseableStocks(mesPPOutboundOrderDetails.MaterielCode, mesPPOutboundOrderDetails.BatchNo, OutboundOrder.WarehouseId);
                List<Dt_StockInfo> stockInfos = _stockService.StockInfoService.GetUseableStocks(mesPPOutboundOrderDetails.MaterialCode, mesPPOutboundOrderDetails.BatchNo, OutboundOrder.WarehouseId);
                stockInfos = stockInfos.Where(x => !stockSelectViews.Select(v => v.PalletCode).Contains(x.PalletCode)).ToList();
                List<Dt_StockInfo> autoAssignStocks = _stockService.StockInfoService.GetOutboundStocks(stockInfos, mesPPOutboundOrderDetails.MaterielCode, needQuantity, out float residueQuantity);
                List<Dt_StockInfo> autoAssignStocks = _stockService.StockInfoService.GetOutboundStocks(stockInfos, mesPPOutboundOrderDetails.MaterialCode, needQuantity, out float residueQuantity);
                mesPPOutboundOrderDetails.LockQuantity += needQuantity - residueQuantity;
                outStocks.AddRange(autoAssignStocks);
                mesPPOutboundOrderDetails.OrderDetailStatus = OrderDetailStatusEnum.AssignOver.ObjToInt();
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/MesPPOutboundOrderService.cs
@@ -33,7 +33,7 @@
            _basicService = basicService;
            _recordService = recordService;
        }
        #region PP出库(旧)
        //public (List<Dt_StockInfo>, Dt_MesPPOutboundOrder, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) AssignStockOutbound(Dt_MesPPOutboundOrder mesPPOutboundOrder)
        //{
        //    List<Dt_StockInfo> outStocks = new List<Dt_StockInfo>();
@@ -138,6 +138,128 @@
        //    return (outStocks, mesPPCutOutboundOrderDetail, outStockLockInfos, locationInfos);
        //}
        #endregion
  
        /// <summary>
        /// PP大卷出库(新)
        /// </summary>
        /// <param name="mesPPOutboundOrder"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public (List<Dt_StockInfo>, Dt_MesPPOutboundOrder, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) AssignPPStockOutbound(Dt_MesPPOutboundOrder mesPPOutboundOrder)
        {
            List<Dt_StockInfo> outStocks = new List<Dt_StockInfo>();
            List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>();
            List<Dt_LocationInfo> locationInfos = new List<Dt_LocationInfo>();
            float originalNeedQuantity = mesPPOutboundOrder.OrderQuantity;
            float needQuantity = originalNeedQuantity;
            //获取库存
            List<Dt_StockInfo> stockInfos = _stockService.StockInfoService.GetUseablePPStocks(mesPPOutboundOrder.MaterialCode, "", mesPPOutboundOrder.WarehouseId);
            if (!stockInfos.Any())
            {
                throw new Exception($"未找到可分配库存");
            }
            List<Dt_StockInfo> autoAssignStocks = _stockService.StockInfoService.GetOutboundPPStocks(stockInfos, mesPPOutboundOrder.MaterialCode, needQuantity, out float residueQuantity);
            if (residueQuantity > 0)
            {
                throw new Exception($"库存不足");
            }
            autoAssignStocks.OrderBy(x => x.Details.FirstOrDefault()?.StockQuantity).ToList();
            outStocks.AddRange(autoAssignStocks);
            for (int j = 0; j < autoAssignStocks.Count; j++)
            {
                float detailAssignQuantity = outStockLockInfos.Where(x => x.MaterielCode == mesPPOutboundOrder.MaterialCode).Sum(x => x.AssignQuantity);//出库订单明细已分配数量
                float palletAssignQuantity = outStockLockInfos.Where(x => x.MaterielCode == mesPPOutboundOrder.MaterialCode && x.PalletCode == autoAssignStocks[j].PalletCode).Sum(x => x.AssignQuantity);//出库详情已分配数量
                float palletOutboundQuantity = autoAssignStocks[j].Details.Sum(x => x.OutboundQuantity);
                if (palletAssignQuantity < palletOutboundQuantity)//如果出库详情已分配数量小于托盘已分配数量,则可以继续添加该托盘出库信息
                {
                    float orderDetailNeedQuantity = mesPPOutboundOrder.OrderQuantity - detailAssignQuantity;
                    if (orderDetailNeedQuantity > autoAssignStocks[j].Details.Sum(x => x.OutboundQuantity) - palletAssignQuantity)
                    {
                        mesPPOutboundOrder.LockQuantity += autoAssignStocks[j].Details.Sum(x => x.OutboundQuantity) - palletAssignQuantity;
                        Dt_OutStockLockInfo outStockLockInfo = _outStockLockInfoService.GetOutStockLockInfo(mesPPOutboundOrder, autoAssignStocks[j], autoAssignStocks[j].Details.Sum(x => x.OutboundQuantity) - palletAssignQuantity);
                        outStockLockInfos.Add(outStockLockInfo);
                    }
                    else
                    {
                        Dt_OutStockLockInfo outStockLockInfo = _outStockLockInfoService.GetOutStockLockInfo(mesPPOutboundOrder, autoAssignStocks[j], mesPPOutboundOrder.OrderQuantity - mesPPOutboundOrder.LockQuantity);
                        outStockLockInfos.Add(outStockLockInfo);
                        mesPPOutboundOrder.LockQuantity = mesPPOutboundOrder.OrderQuantity;
                        break;
                    }
                }
            }
            locationInfos.AddRange(_basicService.LocationInfoService.Repository.GetLocationInfos(outStocks.Select(x => x.LocationCode).ToList()));
            return (outStocks, mesPPOutboundOrder, outStockLockInfos, locationInfos);
        }
        /// <summary>
        /// PP小卷出库(新)
        /// </summary>
        /// <param name="mesPPOutboundOrder"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public (List<Dt_StockInfo>, List<Dt_MesPPCutOutboundOrderDetail>, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) AssignPPCutStockOutbound(Dt_MesPPCutOutboundOrder mesPPCutOutboundOrder,List<Dt_MesPPCutOutboundOrderDetail> mesPPCutOutboundOrderDetails)
        {
            List<Dt_StockInfo> outStocks = new List<Dt_StockInfo>();
            List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>();
            List<Dt_LocationInfo> locationInfos = new List<Dt_LocationInfo>();
            foreach (var item in mesPPCutOutboundOrderDetails)
            {
                float originalNeedQuantity = item.OrderQuantity;
                float needQuantity = originalNeedQuantity;
                //获取库存
                List<Dt_StockInfo> stockInfos = _stockService.StockInfoService.GetUseablePPStocks(item.MaterialCode, "", mesPPCutOutboundOrder.WarehouseId);
                if (!stockInfos.Any())
                {
                    throw new Exception($"未找到可分配库存");
                }
                List<Dt_StockInfo> autoAssignStocks = _stockService.StockInfoService.GetOutboundPPStocks(stockInfos, item.MaterialCode, needQuantity, out float residueQuantity,item.TargetAddressCode);
                if (residueQuantity > 0)
                {
                    throw new Exception($"库存不足");
                }
                autoAssignStocks.OrderBy(x => x.Details.FirstOrDefault()?.StockQuantity).ToList();
                outStocks.AddRange(autoAssignStocks);
                for (int j = 0; j < autoAssignStocks.Count; j++)
                {
                    float detailAssignQuantity = outStockLockInfos.Where(x => x.MaterielCode == item.MaterialCode).Sum(x => x.AssignQuantity);//出库订单明细已分配数量
                    float palletAssignQuantity = outStockLockInfos.Where(x => x.MaterielCode == item.MaterialCode && x.PalletCode == autoAssignStocks[j].PalletCode).Sum(x => x.AssignQuantity);//出库详情已分配数量
                    float palletOutboundQuantity = autoAssignStocks[j].Details.Sum(x => x.OutboundQuantity);
                    if (palletAssignQuantity < palletOutboundQuantity)//如果出库详情已分配数量小于托盘已分配数量,则可以继续添加该托盘出库信息
                    {
                        float orderDetailNeedQuantity = item.OrderQuantity - detailAssignQuantity;
                        if (orderDetailNeedQuantity > autoAssignStocks[j].Details.Sum(x => x.OutboundQuantity) - palletAssignQuantity)
                        {
                            item.LockQuantity += autoAssignStocks[j].Details.Sum(x => x.OutboundQuantity) - palletAssignQuantity;
                            Dt_OutStockLockInfo outStockLockInfo = _outStockLockInfoService.GetOutStockLockInfos(mesPPCutOutboundOrder, item, autoAssignStocks[j]);
                            outStockLockInfos.Add(outStockLockInfo);
                        }
                        else
                        {
                            Dt_OutStockLockInfo outStockLockInfo = _outStockLockInfoService.GetOutStockLockInfos(mesPPCutOutboundOrder, item , autoAssignStocks[j]);
                            outStockLockInfos.Add(outStockLockInfo);
                            item.LockQuantity = item.OrderQuantity;
                            break;
                        }
                    }
                }
            }
            locationInfos.AddRange(_basicService.LocationInfoService.Repository.GetLocationInfos(outStocks.Select(x => x.LocationCode).ToList()));
            return (outStocks, mesPPCutOutboundOrderDetails, outStockLockInfos, locationInfos);
        }
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/OutStockLockInfoService.cs
@@ -132,6 +132,34 @@
        /// <param name="assignQuantity"></param>
        /// <param name="taskNum"></param>
        /// <returns></returns>
        public Dt_OutStockLockInfo GetOutStockLockInfos(Dt_MesPPCutOutboundOrder mesPPCutOutboundOrder, Dt_MesPPCutOutboundOrderDetail mesPPCutOutboundOrderDetail, Dt_StockInfo outStock, int? taskNum = null)
        {
                Dt_OutStockLockInfo outStockLockInfo = new Dt_OutStockLockInfo()
                {
                    PalletCode = outStock.PalletCode,
                    AssignQuantity = outStock.Details.Where(x => x.MaterielCode == mesPPCutOutboundOrderDetail.MaterialCode).Sum(x => x.OutboundQuantity),
                    MaterielCode = mesPPCutOutboundOrderDetail.MaterialCode,
                    BatchNo = outStock.Details.FirstOrDefault().BatchNo,
                    LocationCode = outStock.LocationCode,
                    MaterielName = mesPPCutOutboundOrderDetail.MaterialName,
                    OrderDetailId = mesPPCutOutboundOrderDetail.Id,
                    OrderNo = mesPPCutOutboundOrder.OrderNo,
                    OrderType = mesPPCutOutboundOrder.OrderType,
                    OriginalQuantity = outStock.Details.Where(x => x.MaterielCode == mesPPCutOutboundOrderDetail.MaterialCode).Sum(x => x.StockQuantity),
                    Status = taskNum == null ? OutLockStockStatusEnum.已分配.ObjToInt() : OutLockStockStatusEnum.出库中.ObjToInt(),
                    StockId = outStock.Id,
                    TaskNum = taskNum,
                    OrderQuantity = mesPPCutOutboundOrderDetail.OrderQuantity,
                    Unit = mesPPCutOutboundOrderDetail.Unit,
                    ProductionDate = outStock.Details.Where(x => x.MaterielCode == mesPPCutOutboundOrderDetail.MaterialCode).FirstOrDefault()?.ProductionDate,
                    EffectiveDate = outStock.Details.Where(x => x.MaterielCode == mesPPCutOutboundOrderDetail.MaterialCode).FirstOrDefault()?.EffectiveDate
                };
            return outStockLockInfo;
        }
        public List<Dt_OutStockLockInfo> GetOutStockLockInfos(Dt_MesPPCutOutboundOrder mesPPCutOutboundOrder, Dt_MesPPCutOutboundOrderDetail mesPPCutOutboundOrderDetail, List<Dt_StockInfo> outStock, int? taskNum = null)
        {
            List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>();
@@ -141,22 +169,22 @@
                Dt_OutStockLockInfo outStockLockInfo = new Dt_OutStockLockInfo()
                {
                    PalletCode = item.PalletCode,
                    AssignQuantity = item.Details.Where(x => x.MaterielCode == mesPPCutOutboundOrderDetail.MaterielCode).Sum(x => x.OutboundQuantity),
                    MaterielCode = mesPPCutOutboundOrderDetail.MaterielCode,
                    AssignQuantity = item.Details.Where(x => x.MaterielCode == mesPPCutOutboundOrderDetail.MaterialCode).Sum(x => x.OutboundQuantity),
                    MaterielCode = mesPPCutOutboundOrderDetail.MaterialCode,
                    BatchNo = item.Details.FirstOrDefault().BatchNo,
                    LocationCode = item.LocationCode,
                    MaterielName = mesPPCutOutboundOrderDetail.MaterielName,
                    MaterielName = mesPPCutOutboundOrderDetail.MaterialName,
                    OrderDetailId = mesPPCutOutboundOrderDetail.Id,
                    OrderNo = mesPPCutOutboundOrder.OrderNo,
                    OrderType = mesPPCutOutboundOrder.OrderType,
                    OriginalQuantity = item.Details.Where(x => x.MaterielCode == mesPPCutOutboundOrderDetail.MaterielCode).Sum(x => x.StockQuantity),
                    OriginalQuantity = item.Details.Where(x => x.MaterielCode == mesPPCutOutboundOrderDetail.MaterialCode).Sum(x => x.StockQuantity),
                    Status = taskNum == null ? OutLockStockStatusEnum.已分配.ObjToInt() : OutLockStockStatusEnum.出库中.ObjToInt(),
                    StockId = item.Id,
                    TaskNum = taskNum,
                    OrderQuantity = mesPPCutOutboundOrderDetail.OrderQuantity,
                    Unit = mesPPCutOutboundOrderDetail.Unit,
                    ProductionDate = item.Details.Where(x => x.MaterielCode == mesPPCutOutboundOrderDetail.MaterielCode).FirstOrDefault()?.ProductionDate,
                    EffectiveDate = item.Details.Where(x => x.MaterielCode == mesPPCutOutboundOrderDetail.MaterielCode).FirstOrDefault()?.EffectiveDate
                    ProductionDate = item.Details.Where(x => x.MaterielCode == mesPPCutOutboundOrderDetail.MaterialCode).FirstOrDefault()?.ProductionDate,
                    EffectiveDate = item.Details.Where(x => x.MaterielCode == mesPPCutOutboundOrderDetail.MaterialCode).FirstOrDefault()?.EffectiveDate
                };
                outStockLockInfos.Add(outStockLockInfo);
            }
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoService.cs
@@ -11,6 +11,7 @@
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Common.StockEnum;
using WIDESEA_Common.WareHouseEnum;
using WIDESEA_Core;
using WIDESEA_Core.BaseServices;
using WIDESEA_Core.Enums;
@@ -290,6 +291,84 @@
            residueQuantity = needQuantity;
            return outStocks;
        }
    //PP大卷出库(新)
    public List<Dt_StockInfo> GetOutboundPPStocks(List<Dt_StockInfo> stockInfos, string materielCode, float needQuantity, out float residueQuantity,string targetAddressCode = "")
    {
        List<Dt_StockInfo> outStocks = new List<Dt_StockInfo>();
        stockInfos = stockInfos.OrderBy(x =>
            x.WarehouseId == WarehouseEnum.HA581.ObjToInt()? 0 :
            x.WarehouseId == WarehouseEnum.HA58.ObjToInt()? 1 :
            2
        ).ToList();
        // è®¡ç®—总可用库存(仅统计指定物料编码)
        float stockTotalQuantity = stockInfos
            .Select(x => x.Details
                .Where(d => d.MaterielCode == materielCode)
                .Sum(v => v.StockQuantity - v.OutboundQuantity)
            ).Sum(x => x);
        if (stockTotalQuantity >= needQuantity)//库存够
        {
            int index = 0;
            while (needQuantity > 0 && index < stockInfos.Count)
            {
                Dt_StockInfo stockInfo = stockInfos[index];
                decimal useableStockQuantity = stockInfo.Details
                    .Where(x => x.MaterielCode == materielCode)
                    .Sum(x => (decimal)x.StockQuantity - (decimal)x.OutboundQuantity);
                if (useableStockQuantity < (decimal)needQuantity && useableStockQuantity > 0)
                {
                    // å¯ç”¨é‡ä¸è¶³ï¼Œå…¨éƒ¨å‡ºåº“
                    stockInfo.Details.ForEach(x =>
                    {
                        if (x.MaterielCode == materielCode)
                            x.OutboundQuantity = x.StockQuantity;
                    });
                    needQuantity = (float)((decimal)needQuantity - useableStockQuantity);
                }
                else if (useableStockQuantity > 0)
                {
                    stockInfo.Details.ForEach(x =>
                    {
                        if (x.StockQuantity > x.OutboundQuantity && x.MaterielCode == materielCode)
                        {
                            decimal currentStock = (decimal)x.StockQuantity;
                            decimal currentOutbound = (decimal)x.OutboundQuantity;
                            decimal currentNeed = (decimal)needQuantity;
                            decimal available = currentStock - currentOutbound;
                            if (available >= currentNeed)
                            {
                                x.OutboundQuantity = (float)(currentOutbound + currentNeed);
                                needQuantity = 0;
                            }
                            else
                            {
                                needQuantity = (float)(currentNeed - available);
                                x.OutboundQuantity = x.StockQuantity;
                            }
                        }
                    });
                }
                // ä»…将有实际出库的库存加入结果集
                if (useableStockQuantity > 0)
                    {
                        stockInfo.Remark = targetAddressCode;
                        outStocks.Add(stockInfo);
                    }
                index++;
            }
        }
        else
        {
            throw new Exception("库存不足");
        }
        residueQuantity = needQuantity;
        return outStocks;
    }
        public List<Dt_StockInfo> GetUseableStocks(string materielCode, string batchNo, int warehoseId)
        {
@@ -301,6 +380,13 @@
            return BaseDal.GetStockInfos(materielCode, batchNo, locationCodes);
        }
        //PP大卷出库(新)
        public List<Dt_StockInfo> GetUseablePPStocks(string materielCode, string batchNo, int warehoseId)
        {
            List<string> locationCodes = _basicRepository.LocationInfoRepository.GetCanOutPPLocationCodes(warehoseId);
            return BaseDal.GetStockInfos(materielCode, batchNo, locationCodes);
        }
        public List<Dt_StockInfo> GetUseableStocks(string materielCode, string batchNo, string palletcode, int warehoseId)
        {
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/MesTaskService.cs
@@ -31,6 +31,10 @@
using SqlSugar;
using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
using WIDESEA_Core.CodeConfigEnum;
using WIDESEA_DTO.Basic;
using System.Globalization;
using System.Collections;
namespace WIDESEA_TaskInfoService
{
@@ -518,6 +522,29 @@
            return model;
        }
        public MesMaterialLotaAceptModel PPGetMesMaterialLotaAceptModel(Dt_StockInfo stockInfo, Dt_StockInfoDetail stockInfoDetail, string taskNo, string warehouseCode, float quantity, string cutedType = "", float ppWidth = 0)
        {
            MesMaterialLotaAceptModel model = new MesMaterialLotaAceptModel()
            {
                CarrierCode = stockInfo.PalletCode,
                CutedType = cutedType,
                ExpirationDate = stockInfoDetail.EffectiveDate,
                MaterialBarCode = stockInfoDetail.SerialNumber,
                MaterialCode = stockInfoDetail.MaterielCode,
                MaterialLot = stockInfoDetail.MaterielCode + "," + stockInfoDetail.BatchNo,
                MaterialName = stockInfoDetail.MaterielName,
                PPWidth = ppWidth,
                ProductionDate = stockInfoDetail.ProductionDate,
                Quantity = quantity,
                Supplier = "",
                TaskNo = taskNo,
                Type = 2,
                WarehouseArea = warehouseCode,
                WarehouseLocation = warehouseCode
            };
            return model;
        }
        /// <summary>
        /// åŸºæ¿å‡ºåº“
        /// </summary>
@@ -719,7 +746,6 @@
            MesResponseContent modelCount = new MesResponseContent();
            try
            {
                Dt_Warehouse warehouse = _basicService.WarehouseService.Repository.QueryFirst(x => x.WarehouseCode == WarehouseEnum.HA58.ToString());
                if (warehouse == null)
                {
@@ -742,7 +768,7 @@
                    };
                    mesPPOutboundOrderDetail.Add(dt_MesPPOutboundOrderDetail);
                }
                Dt_MesPPOutboundOrder mesOutboundOrder = new Dt_MesPPOutboundOrder()
                Dt_MesPPOutboundOrder mesPPOutboundOrder1 = new Dt_MesPPOutboundOrder()
                {
                    CreateType = OrderCreateTypeEnum.UpperSystemPush.ObjToInt(),
                    MaterialCode = model.MaterialCode,
@@ -758,67 +784,111 @@
                    Details = mesPPOutboundOrderDetail
                };
                #region
                //Db.InsertNav(mesOutboundOrder).Include(x=>x.Details).ExecuteCommand();
                //    List<Dt_Task> tasks = new List<Dt_Task>();
                List<Dt_Task> tasks = new List<Dt_Task>();
                //    List<Dt_StockInfo>? stockInfos = null;
                //    List<Dt_OutStockLockInfo>? outStockLockInfos = null;
                //    List<Dt_LocationInfo>? locationInfos = null;
                //    {
                //(List<Dt_StockInfo>, Dt_MesPPOutboundOrder, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) result = _outboundService.MesPPOutboundOrderService.AssignStockOutbound(mesOutboundOrder);
                //        if (result.Item1 != null && result.Item1.Count > 0)
                //        {
                //            tasks = GetTasks(result.Item1, TaskTypeEnum.MesOutbound);
                //            result.Item2.OrderStatus = OrderDetailStatusEnum.Outbound.ObjToInt();
                //            result.Item3.ForEach(x =>
                //            {
                //                x.Status = OutLockStockStatusEnum.出库中.ObjToInt();
                //            });
                List<Dt_StockInfo>? stockInfos = null;
                List<Dt_OutStockLockInfo>? outStockLockInfos = null;
                List<Dt_LocationInfo>? locationInfos = null;
                List<Dt_MaterielCodeInfo> materielCodes = new List<Dt_MaterielCodeInfo>();
                {
                    (List<Dt_StockInfo>, Dt_MesPPOutboundOrder, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) result = _outboundService.MesPPOutboundOrderService.AssignPPStockOutbound(mesPPOutboundOrder1);
                    if (result.Item1 != null && result.Item1.Count > 0)
                    {
                        tasks = GetTasks(result.Item1, TaskTypeEnum.MesPPOutbound);
                        result.Item2.OrderStatus = OrderDetailStatusEnum.Outbound.ObjToInt();
                        result.Item3.ForEach(x =>
                        {
                            x.Status = OutLockStockStatusEnum.出库中.ObjToInt();
                        });
                //            stockInfos = result.Item1;
                //            mesOutboundOrder = result.Item2;
                //            outStockLockInfos = result.Item3;
                //            locationInfos = result.Item4;
                //            mesPPOutboundOrderDetail.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt();
                        stockInfos = result.Item1;
                        mesPPOutboundOrder1 = result.Item2;
                        outStockLockInfos = result.Item3;
                        locationInfos = result.Item4;
                        foreach (var item in mesPPOutboundOrderDetail)
                        {
                            item.OrderDetailStatus = OrderDetailStatusEnum.Over.ObjToInt();
                        }
                //        }
                //        else
                //        {
                //            throw new Exception("无库存");
                //        }
                //    }
                //    tasks.ForEach(x =>
                //    {
                //        x.TargetAddress = model.TargetAddressCode;
                //    });
                //    _unitOfWorkManage.BeginTran();
                    }
                    else
                    {
                        throw new Exception("无库存");
                    }
                }
                tasks.ForEach(x =>
                {
                    if (x.Roadway.Contains("AGV_PP"))
                    {
                        x.TargetAddress = model.TargetAddressCode;
                    }
                //    int id = BaseDal.AddData(tasks);
                //    outStockLockInfos.ForEach(x =>
                //    {
                //        x.OrderNo = mesOutboundOrder.TaskNo;
                //        x.OrderDetailId = id;
                //    });
                //    //_outboundService.MesPPOutboundOrderService.Repository.AddData(mesOutboundOrder);
                //    Db.InsertNav(mesOutboundOrder).Include(x => x.Details).ExecuteCommand();
                //    if (stockInfos != null && stockInfos.Count > 0 && outStockLockInfos != null && outStockLockInfos.Count > 0 && locationInfos != null && locationInfos.Count > 0)
                //    {
                //        WebResponseContent content = _outboundService.MesOutboundOrderService.LockOutboundStockDataUpdate(stockInfos, outStockLockInfos, locationInfos, tasks: tasks);
                //        if (!content.Status)
                //        {
                //            _unitOfWorkManage.RollbackTran();
                //            return MesResponseContent.Instance.Error(content.Message);
                //        }
                //    }
                //    _unitOfWorkManage.CommitTran();
                //    PushTasksToWCS(tasks);
                //}
                #endregion
                });
                _unitOfWorkManage.BeginTran();
                Db.InsertNav(mesOutboundOrder).Include(x => x.Details).ExecuteCommand();
                int id = BaseDal.AddData(tasks);
                outStockLockInfos.ForEach(x =>
                {
                    x.OrderNo = mesPPOutboundOrder1.TaskNo;
                    x.OrderDetailId = id;
                });
                Db.InsertNav(mesPPOutboundOrder1).Include(x => x.Details).ExecuteCommand();
                if (stockInfos.Count > 0 && stockInfos != null)
                {
                    var lkstockInfo = stockInfos.Where(x => x.LocationCode.Contains("SC01_PP")).ToList();
                    if(lkstockInfo != null)
                    {
                        foreach (var item in lkstockInfo)
                        {
                            Dt_MaterielInfo materielInfo = BaseDal.Db.Queryable<Dt_MaterielInfo>().Where(x => x.MaterielCode == item.Details.FirstOrDefault().MaterielCode).First();
                            if(materielInfo == null)
                            {
                                return MesResponseContent.Instance.Error($"未找到物料编号{item.Details.FirstOrDefault().MaterielCode}的物料信息");
                            }
                            Dt_MaterielCodeInfo materielCodeInfo = new Dt_MaterielCodeInfo()
                            {
                                MaterielCode = item.Details.FirstOrDefault().MaterielCode,
                                MaterielName = materielInfo.MaterielName,
                                MaterielSpec = materielInfo.MaterielSpec,
                                LotNo = item.Details.FirstOrDefault().BatchNo,
                                ProductionDate = item.Details.FirstOrDefault().ProductionDate.ObjToDate(),
                                EffectiveDate = item.Details.FirstOrDefault().EffectiveDate.ObjToDate(),
                                PurchaseOrderNo = DateTime.Now.ToString("yyMMdd") + item.Details.FirstOrDefault().BatchNo,
                                Quantity = item.Details.FirstOrDefault().StockQuantity,
                                MaterielLength = (decimal)materielInfo.MaterielLength,
                                WarehouseId = warehouse.WarehouseId
                            };
                            materielCodes.Add(materielCodeInfo);
                        }
                        Db.Insertable(materielCodes).ExecuteCommand();
                    }
                }
                if (stockInfos != null && stockInfos.Count > 0 && outStockLockInfos != null && outStockLockInfos.Count > 0 && locationInfos != null && locationInfos.Count > 0)
                {
                    WebResponseContent content = _outboundService.MesOutboundOrderService.LockOutboundStockDataUpdate(stockInfos, outStockLockInfos, locationInfos, tasks: tasks);
                    if (!content.Status)
                    {
                        _unitOfWorkManage.RollbackTran();
                        return MesResponseContent.Instance.Error(content.Message);
                    }
                }
                _unitOfWorkManage.CommitTran();
                var pktask = tasks.Where(x => x.Roadway.Contains("AGV_PP")).ToList();
                if(pktask != null&& pktask.Count>0)
                {
                    PushTasksToWCS(pktask, "AGV_PP");
                }
                var lktask = tasks.Where(x => x.Roadway.Contains("SC01_PP")).ToList();
                if (lktask != null&& lktask.Count>0)
                {
                    PushTasksToWCS(lktask);
                }
                #endregion
            //_unitOfWorkManage.BeginTran();
            //Db.InsertNav(mesOutboundOrder).Include(x => x.Details).ExecuteCommand();
            //_unitOfWorkManage.CommitTran();
                return MesResponseContent.Instance.OK();
            }
            catch (Exception ex)
@@ -839,7 +909,7 @@
            try
            {
                Dt_Warehouse warehouse = _basicService.WarehouseService.Repository.QueryFirst(x => x.WarehouseCode == WarehouseEnum.HA58.ToString());
                Dt_Warehouse warehouse = _basicService.WarehouseService.Repository.QueryFirst(x => x.WarehouseCode == WarehouseEnum.HA581.ToString());
                if (warehouse == null)
                {
                    return MesResponseContent.Instance.Error("仓库基础信息未配置");
@@ -859,67 +929,65 @@
                    CreateType = OrderCreateTypeEnum.UpperSystemPush.ObjToInt(),
                    TaskNo = model.TaskNo,
                    OrderType = OutOrderTypeEnum.Issue.ObjToInt(),
                    OrderStatus = OutOrderStatusEnum.未开始.ObjToInt(),
                    OrderStatus = OutOrderStatusEnum.出库中.ObjToInt(),
                    WarehouseId = warehouse.WarehouseId,
                    Details = mesPPCutOutboundOrderDetail,
                };
                _unitOfWorkManage.BeginTran();
                Db.InsertNav(mesPPOutboundOrder).Include(x => x.Details).ExecuteCommand();
                _unitOfWorkManage.CommitTran();
                #region
                //List<Dt_Task> tasks = new List<Dt_Task>();
                List<Dt_Task> tasks = new List<Dt_Task>();
                //List<Dt_StockInfo>? stockInfos = null;
                //List<Dt_OutStockLockInfo>? outStockLockInfos = null;
                //List<Dt_LocationInfo>? locationInfos = null;
                //{
                //(List<Dt_StockInfo>, Dt_MesPPCutOutboundOrderDetail, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) result = _outboundService.MesPPOutboundOrderService.AssignStockOutbound(mesPPOutboundOrder, mesPPCutOutboundOrderDetail);
                //    if (result.Item1 != null && result.Item1.Count > 0)
                //    {
                //        tasks = GetTasks(result.Item1, TaskTypeEnum.MesOutbound);
                //        result.Item2.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt();
                //        result.Item3.ForEach(x =>
                //        {
                //            x.Status = OutLockStockStatusEnum.出库中.ObjToInt();
                //        });
                List<Dt_StockInfo>? stockInfos = null;
                List<Dt_OutStockLockInfo>? outStockLockInfos = null;
                List<Dt_LocationInfo>? locationInfos = null;
                {
                    (List<Dt_StockInfo>, List<Dt_MesPPCutOutboundOrderDetail>, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) result = _outboundService.MesPPOutboundOrderService.AssignPPCutStockOutbound(mesPPOutboundOrder, mesPPCutOutboundOrderDetail);
                    if (result.Item1 != null && result.Item1.Count > 0)
                    {
                        tasks = GetTasks(result.Item1, TaskTypeEnum.MesPPCutOutbound);
                        result.Item2.ForEach(x =>
                        {
                            x.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt();
                        });
                        result.Item3.ForEach(x =>
                        {
                            x.Status = OutLockStockStatusEnum.出库中.ObjToInt();
                        });
                //        stockInfos = result.Item1;
                //        mesPPCutOutboundOrderDetail = result.Item2;
                //        outStockLockInfos = result.Item3;
                //        locationInfos = result.Item4;
                        stockInfos = result.Item1;
                        mesPPCutOutboundOrderDetail = result.Item2;
                        outStockLockInfos = result.Item3;
                        locationInfos = result.Item4;
                //    }
                //    else
                //    {
                //        throw new Exception("无库存");
                //    }
                //}
                //tasks.ForEach(x =>
                //{
                //    x.TargetAddress = mesPPCutOutboundOrderDetail.TargetAddressCode;
                //});
                //_unitOfWorkManage.BeginTran();
                    }
                    else
                    {
                        throw new Exception("无库存");
                    }
                }
                //int id = BaseDal.AddData(tasks);
                //outStockLockInfos.ForEach(x =>
                //{
                //    x.OrderNo = mesPPOutboundOrder.TaskNo;
                //    x.OrderDetailId = id;
                //});
                ////_outboundService.MesPPOutboundOrderService.Repository.AddData(mesOutboundOrder);
                int id = BaseDal.AddData(tasks);
                outStockLockInfos.ForEach(x =>
                {
                    x.OrderNo = mesPPOutboundOrder.TaskNo;
                });
                if (stockInfos != null && stockInfos.Count > 0 && outStockLockInfos != null && outStockLockInfos.Count > 0 && locationInfos != null && locationInfos.Count > 0)
                {
                    WebResponseContent content = _outboundService.MesOutboundOrderService.LockOutboundStockDataUpdate(stockInfos, outStockLockInfos, locationInfos, tasks: tasks);
                    if (!content.Status)
                    {
                        _unitOfWorkManage.RollbackTran();
                        return MesResponseContent.Instance.Error(content.Message);
                    }
                }
                //Db.InsertNav(mesPPOutboundOrder).Include(x => x.Details).ExecuteCommand();
                //if (stockInfos != null && stockInfos.Count > 0 && outStockLockInfos != null && outStockLockInfos.Count > 0 && locationInfos != null && locationInfos.Count > 0)
                //{
                //    WebResponseContent content = _outboundService.MesOutboundOrderService.LockOutboundStockDataUpdate(stockInfos, outStockLockInfos, locationInfos, tasks: tasks);
                //    if (!content.Status)
                //    {
                //        _unitOfWorkManage.RollbackTran();
                //        return MesResponseContent.Instance.Error(content.Message);
                //    }
                //}
                //_unitOfWorkManage.CommitTran();
                //PushTasksToWCS(tasks, "AGV_PP");
                _unitOfWorkManage.CommitTran();
                PushTasksToWCS(tasks, "AGV_PP");
                #endregion
                return MesResponseContent.Instance.OK();
            }
@@ -1105,36 +1173,88 @@
            MesResponseContent content = new MesResponseContent();
            try
            {
                //需判断查询立库,平库
                Dt_Warehouse warehouse = _basicRepository.WarehouseRepository.QueryFirst(x => x.WarehouseCode == WarehouseEnum.HA58.ToString());
                List<Dt_StockInfo> stockInfos = _stockRepository.StockInfoRepository.Db.Queryable<Dt_StockInfo>().Where(x =>
                x.WarehouseId == warehouse.WarehouseId &&
                x.StockStatus == (int)StockStatusEmun.入库完成).Includes(x => x.Details).ToList();
                Dt_StockInfo? stockInfo = stockInfos.FirstOrDefault(x => x.Details.Any(x => x.MaterielCode == model.MaterialCode && x.CutedWidth == model.CutedWidth));
                if (stockInfo == null)
                Dt_Warehouse lkwarehouse = _basicRepository.WarehouseRepository.QueryFirst(x => x.WarehouseCode == WarehouseEnum.HA58.ToString());
                Dt_Warehouse pkwarehouse = _basicRepository.WarehouseRepository.QueryFirst(x => x.WarehouseCode == WarehouseEnum.HA581.ToString());
                if (lkwarehouse == null || pkwarehouse == null)
                {
                    return content.Error($"PP仓立库/平库:物料编号:{model.MaterialCode},裁切宽:{model.CutedWidth},未找到此物料库存信息");
                    return content.Error("立库或平库仓库信息不存在");
                }
                var stock = stockInfo.Details.FirstOrDefault();
                if (stock != null)
                List<Dt_StockInfo> lkstockInfos = _stockRepository.StockInfoRepository.Db
                    .Queryable<Dt_StockInfo>()
                    .Where(x => x.WarehouseId == lkwarehouse.WarehouseId
                             && x.StockStatus == (int)StockStatusEmun.入库完成)
                    .Includes(x => x.Details)
                    .ToList();
                List<Dt_StockInfo> lkTargetStockInfos = lkstockInfos
                    .Where(x => x.Details != null && x.Details.Any(d => d.MaterielCode == model.MaterialCode))
                    .ToList();
                List<Dt_StockInfo> pkstockInfos = _stockRepository.StockInfoRepository.Db
                    .Queryable<Dt_StockInfo>()
                    .Where(x => x.WarehouseId == pkwarehouse.WarehouseId
                             && x.StockStatus == (int)StockStatusEmun.入库完成)
                    .Includes(x => x.Details)
                    .ToList();
                List<Dt_StockInfo> pkTargetStockInfos = pkstockInfos
                    .Where(x => x.Details != null && x.Details.Any(d => d.MaterielCode == model.MaterialCode))
                    .ToList();
                decimal lkTotalQuantity = (decimal)lkTargetStockInfos
                    .SelectMany(x => x.Details ?? new List<Dt_StockInfoDetail>())
                    .Where(d => d.MaterielCode == model.MaterialCode)
                    .Sum(d => d.StockQuantity);
                // å¹³åº“总数
                decimal pkTotalQuantity = (decimal)pkTargetStockInfos
                    .SelectMany(x => x.Details ?? new List<Dt_StockInfoDetail>())
                    .Where(d => d.MaterielCode == model.MaterialCode)
                    .Sum(d => d.StockQuantity);
                if (lkTotalQuantity <= 0 && pkTotalQuantity <= 0)
                {
                    content.Content = new
                    return content.Error($"PP仓立库/平库:物料编号:{model.MaterialCode},未找到此物料库存信息");
                }
                content.Content = new List<object>
                    {
                        MaterialCode = stock.MaterielCode,
                        Quantity = stock.StockQuantity,
                        Unit = stock.Unit,
                        Warehouse = warehouse.WarehouseCode,
                        WarehouseName = warehouse.WarehouseName,
                        CutedWidth = stock.CutedWidth,
                        CarrierCode = stockInfo.PalletCode,
                        MaterialLot = stock.BatchNo,
                     new
                     {
                         MaterialCode = model.MaterialCode,
                         Quantity = lkTotalQuantity,
                         Unit = lkTargetStockInfos.SelectMany(x => x.Details ?? new List<Dt_StockInfoDetail>())
                                                  .Where(d => d.MaterielCode == model.MaterialCode)
                                                  .FirstOrDefault()?.Unit ?? "ç®±",
                         Warehouse = lkwarehouse.WarehouseCode,
                         WarehouseName = lkwarehouse.WarehouseName,
                         CutedWidth = 0,
                         CarrierCode = "",
                         MaterialLot = "",
                     },
                     new
                     {
                         MaterialCode = model.MaterialCode,
                         Quantity = pkTotalQuantity,
                         Unit = pkTargetStockInfos.SelectMany(x => x.Details ?? new List<Dt_StockInfoDetail>())
                                                  .Where(d => d.MaterielCode == model.MaterialCode)
                                                  .FirstOrDefault()?.Unit ?? "ç®±",
                         Warehouse = pkwarehouse.WarehouseCode,
                         WarehouseName = pkwarehouse.WarehouseName,
                         CutedWidth = 0,
                         CarrierCode = "",
                         MaterialLot = "",
                     }
                    };
                }
                return content.OK();
            }
            catch (Exception ex)
            {
                return MesResponseContent.Instance.Error(ex.Message);
                return MesResponseContent.Instance.Error($"查询库存失败:{ex.Message}");
            }
        }
        
@@ -1672,5 +1792,117 @@
            }
            return content;
        }
        public WebResponseContent PPTaskMove(string palletCode, string startPoint, int warehouseId, List<string> serNums)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                Dt_Warehouse warehouse = _basicRepository.WarehouseRepository.QueryFirst(x => x.WarehouseId == warehouseId);
                if (warehouse == null)
                {
                    return WebResponseContent.Instance.Error($"未找到该仓库信息");
                }
                Dt_Task task = Repository.QueryFirst(x => x.PalletCode == palletCode && x.WarehouseId == warehouseId);
                if (task != null)
                {
                    return WebResponseContent.Instance.Error($"该托盘已生成任务");
                }
                List<MatSerNumAnalysisModel> models = CodeAnalysisHelper.CodeAnalysis<MatSerNumAnalysisModel>(AnalysisCodeEnum.PPPKSerNumAnalysis, serNums);
                //验证判断时间格式
                WebResponseContent IsValidContent = IsValidMCDates(models);
                if (!IsValidContent.Status)
                {
                    return content.Error(IsValidContent.Message);
                }
                Dt_Task newTask = new Dt_Task()
                {
                    CurrentAddress = startPoint,
                    Grade = 0,
                    NextAddress = "PPCuttingWarehouse",
                    PalletCode = palletCode,
                    Roadway = "AGV_PP",
                    SourceAddress = startPoint,
                    TargetAddress = "PPCuttingWarehouse",
                    TaskType = TaskTypeEnum.MesPPMove.ObjToInt(),
                    TaskStatus = TaskStatusEnum.New.ObjToInt(),
                    WarehouseId = warehouseId,
                    PalletType = 0,
                    MaterielCode = models.FirstOrDefault()?.MaterielCode,
                    Quantity = (float)models.FirstOrDefault()?.Quantity,
                    BatchNo = models.FirstOrDefault()?.LotNo
                };
                if (palletCode.Contains("DJ"))
                {
                    newTask.PalletType = 2;
                }
                else if (palletCode.Contains("XJ"))
                {
                    newTask.PalletType = 1;
                }
                else
                {
                    return WebResponseContent.Instance.Error("该托盘码错误,或不属于PP平库");
                }
                _unitOfWorkManage.BeginTran();
                int taskId = BaseDal.AddData(newTask);
                newTask.TaskId = taskId;
                _unitOfWorkManage.CommitTran();
                PushTasksToWCS(new List<Dt_Task> { newTask }, "AGV_PP");
                content.OK();
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                content.Error(ex.Message);
            }
            return content;
        }
        public WebResponseContent IsValidMCDates(List<MatSerNumAnalysisModel> analysisModels)
        {
            string[] effDates = analysisModels.Select(x => x.EffectiveDate).Distinct().ToArray();
            string[] ProDates = analysisModels.Select(x => x.ProductionDate).Distinct().ToArray();
            foreach (string effDate in effDates)
            {
                string format = "yyyy-MM-dd"; // ç›®æ ‡æ ¼å¼
                DateTime parsedDate;
                // è§£æžå¹¶éªŒè¯æ ¼å¼
                bool isValid = DateTime.TryParseExact(
                    effDate,
                    format,
                    CultureInfo.InvariantCulture,
                    DateTimeStyles.None,
                    out parsedDate
                );
                if (!isValid)
                {
                    return WebResponseContent.Instance.Error("格式无效或日期不合法");
                }
            }
            foreach (string ProDate in ProDates)
            {
                string format = "yyyy-MM-dd"; // ç›®æ ‡æ ¼å¼
                DateTime parsedDate;
                // è§£æžå¹¶éªŒè¯æ ¼å¼
                bool isValid = DateTime.TryParseExact(
                    ProDate,
                    format,
                    CultureInfo.InvariantCulture,
                    DateTimeStyles.None,
                    out parsedDate
                );
                if (!isValid)
                {
                    return WebResponseContent.Instance.Error("格式无效或日期不合法");
                }
            }
            return WebResponseContent.Instance.OK();
        }
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs
@@ -603,6 +603,14 @@
                }
                Dt_StockInfo stockInfo = _stockService.StockInfoService.Repository.GetStockInfo(task.PalletCode);
                if(task.TaskType == TaskTypeEnum.MesPPMove.ObjToInt())
                {
                    task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
                    BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                    FeedBackWCSTaskCompleted(taskNum);
                    return WebResponseContent.Instance.OK();
                }
                Dt_LocationInfo locationInfo = _basicService.LocationInfoService.Repository.QueryFirst(x => x.LocationCode == task.SourceAddress);
                if (stockInfo == null)
                {
@@ -620,8 +628,11 @@
                List<Dt_OutboundOrderDetail> outboundOrderDetails = new List<Dt_OutboundOrderDetail>();
                List<Dt_MesOutboundOrder> mesOutboundOrders = new List<Dt_MesOutboundOrder>();
                List<Dt_MesPPOutboundOrder> mesPPOutboundOrders = new List<Dt_MesPPOutboundOrder>();
                List<Dt_MesPPCutOutboundOrder> mesPPCutOutboundOrders = new List<Dt_MesPPCutOutboundOrder>();
                List<Dt_MesPPCutOutboundOrderDetail> mesPPCutOutboundOrderDetails = new List<Dt_MesPPCutOutboundOrderDetail>();
                Dt_CheckOrder? checkOrder = null;
                Dt_OutboundOrder? outboundOrder = null;
                Dt_MesPPCutOutboundOrder mesPPCutOutboundOrder = null;
                if ((outStockLockInfos == null || outStockLockInfos.Count == 0) && warehouse.WarehouseCode != WarehouseEnum.HA64.ToString() && warehouse.WarehouseCode != WarehouseEnum.HA154.ToString() && (task.TaskType != TaskTypeEnum.OutEmpty.ObjToInt()))
                {
                    return WebResponseContent.Instance.Error($"未找到出库详情信息");
@@ -643,10 +654,10 @@
                                mesOutboundOrders.Add(mesOutboundOrder);
                            }
                        }
                        //PP出库任务完成判断。。。。。。。。。。。。。。。。。
                        else if (task.TaskType == TaskTypeEnum.Outbound.ObjToInt() && warehouse.WarehouseCode == WarehouseEnum.HA58.ToString())
                        //PP大卷出库任务完成判断
                        else if (task.TaskType == TaskTypeEnum.MesPPOutbound.ObjToInt() && (warehouse.WarehouseCode == WarehouseEnum.HA581.ToString()|| warehouse.WarehouseCode == WarehouseEnum.HA58.ToString()))
                        {
                            Dt_MesPPOutboundOrder mesPPOutboundOrder = _outboundService.MesPPOutboundOrderService.Repository.QueryFirst(x => x.OrderNo == item.OrderNo);
                            Dt_MesPPOutboundOrder mesPPOutboundOrder = _outboundService.MesPPOutboundOrderService.Repository.QueryFirst(x => x.TaskNo == item.OrderNo);
                            if (mesPPOutboundOrder != null)
                            {
                                mesPPOutboundOrder.OverOutQuantity = item.AssignQuantity;
@@ -655,6 +666,25 @@
                                    mesPPOutboundOrder.OrderStatus = OrderDetailStatusEnum.Over.ObjToInt();
                                }
                                mesPPOutboundOrders.Add(mesPPOutboundOrder);
                            }
                        }
                        else if (task.TaskType == TaskTypeEnum.MesPPCutOutbound.ObjToInt() && warehouse.WarehouseCode == WarehouseEnum.HA581.ToString())
                        {
                            Dt_MesPPCutOutboundOrderDetail mesPPCutOutboundOrderDetail = _outboundService.MesPPCutOutboundOrderDetailService.Repository.QueryFirst(x => x.Id == item.OrderDetailId);
                            if (mesPPCutOutboundOrderDetail != null)
                            {
                                mesPPCutOutboundOrder = _outboundService.MesPPCutOutboundOrderService.Repository.QueryFirst(x => x.Id == mesPPCutOutboundOrderDetail.OrderId);
                                if (mesPPCutOutboundOrder == null)
                                {
                                    return WebResponseContent.Instance.Error($"未找到MES小卷出库单信息");
                                }
                                mesPPCutOutboundOrderDetail.OverOutQuantity = item.AssignQuantity;
                                if (mesPPCutOutboundOrderDetail.OverOutQuantity == mesPPCutOutboundOrderDetail.OrderQuantity)
                                {
                                    mesPPCutOutboundOrderDetail.OrderDetailStatus = OrderDetailStatusEnum.Over.ObjToInt();
                                }
                                mesPPCutOutboundOrderDetails.Add(mesPPCutOutboundOrderDetail);
                            }
                        }
                        else
@@ -768,17 +798,36 @@
                BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                _recordService.LocationStatusChangeRecordSetvice.AddLocationStatusChangeRecord(locationInfo, (LocationStatusEnum)beforeStatus, LocationStatusEnum.Free, LocationChangeType.OutboundCompleted, stockInfo.Details.FirstOrDefault()?.OrderNo ?? "", task.TaskNum);
                _unitOfWorkManage.CommitTran();
                //PP出库任务完成判断。。。。。。。。。。。。。。。。。
                //if (warehouse.WarehouseCode == WarehouseEnum.HA58.ToString() && task.TaskType == TaskTypeEnum.Outbound.ObjToInt())
                //{
                //    _outboundService.MesPPOutboundOrderService.Repository.UpdateData(mesPPOutboundOrders);
                //    MesMaterialLotaAceptModel model = GetMesMaterialLotaAceptModel(stockInfo, stockInfo.Details.FirstOrDefault(), mesPPOutboundOrders.FirstOrDefault().TaskNo, warehouse.WarehouseCode, stockInfo.Details.Where(x => x.MaterielCode == mesPPOutboundOrders.FirstOrDefault().MaterialCode).Sum(x => x.StockQuantity));
                //    UploadMesMaterialLotaAcept(model);
                //    _stockService.StockInfoService.Repository.DeleteAndMoveIntoHty(stockInfo, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                //    _stockService.StockInfoDetailService.Repository.DeleteAndMoveIntoHty(stockInfo.Details, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                //}
                //PP大卷出库任务完成判断
                if (task.TaskType == TaskTypeEnum.MesPPOutbound.ObjToInt() && (warehouse.WarehouseCode == WarehouseEnum.HA581.ToString() || warehouse.WarehouseCode == WarehouseEnum.HA58.ToString()))
                {
                    _outboundService.MesPPOutboundOrderService.Repository.UpdateData(mesPPOutboundOrders);
                    MesMaterialLotaAceptModel model = PPGetMesMaterialLotaAceptModel(stockInfo, stockInfo.Details.FirstOrDefault(), mesPPOutboundOrders.FirstOrDefault().TaskNo, warehouse.WarehouseCode, stockInfo.Details.Where(x => x.MaterielCode == mesPPOutboundOrders.FirstOrDefault().MaterialCode).Sum(x => x.StockQuantity));
                    UploadMesMaterialLotaAcept(model);
                    _stockService.StockInfoService.Repository.DeleteAndMoveIntoHty(stockInfo, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                    _stockService.StockInfoDetailService.Repository.DeleteAndMoveIntoHty(stockInfo.Details, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                }
                //PP小卷出库任务完成判断
                if (task.TaskType == TaskTypeEnum.MesPPCutOutbound.ObjToInt() && warehouse.WarehouseCode == WarehouseEnum.HA581.ToString())
                {
                    _outboundService.MesPPCutOutboundOrderDetailService.Repository.UpdateData(mesPPCutOutboundOrderDetails);
                    int completedDetailCount = mesPPCutOutboundOrderDetails.Count(x => x.OrderDetailStatus == OrderDetailStatusEnum.Over.ObjToInt());
                    // åˆ¤æ–­æ‰€æœ‰æ˜Žç»†æ˜¯å¦å®Œæˆ
                    if (completedDetailCount == mesPPCutOutboundOrderDetails.Count)
                    {
                        mesPPCutOutboundOrder.OrderStatus = OutOrderStatusEnum.出库完成.ObjToInt();
                        _outboundService.MesPPCutOutboundOrderService.UpdateData(mesPPCutOutboundOrder);
                    }
                    MesMaterialLotaAceptModel model = PPGetMesMaterialLotaAceptModel(stockInfo, stockInfo.Details.FirstOrDefault(), mesPPCutOutboundOrder.TaskNo, warehouse.WarehouseCode, stockInfo.Details.Where(x => x.MaterielCode == mesPPCutOutboundOrderDetails.FirstOrDefault().MaterialCode).Sum(x => x.StockQuantity));
                    UploadMesMaterialLotaAcept(model);
                    _stockService.StockInfoService.Repository.DeleteAndMoveIntoHty(stockInfo, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                    _stockService.StockInfoDetailService.Repository.DeleteAndMoveIntoHty(stockInfo.Details, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                }
                if (warehouse.WarehouseCode != WarehouseEnum.HA64.ToString() && task.TaskType == TaskTypeEnum.Outbound.ObjToInt())
                {
                    _outboundService.OutboundOrderService.TestOutUpload(outboundOrderDetails.FirstOrDefault().OrderId, outStockLockInfos);
@@ -788,7 +837,7 @@
                    MesMaterialLotaAceptModel model = GetMesMaterialLotaAceptModel(stockInfo, stockInfo.Details.FirstOrDefault(), mesOutboundOrders.FirstOrDefault().TaskNo, warehouse.WarehouseCode, stockInfo.Details.Where(x => x.MaterielCode == mesOutboundOrders.FirstOrDefault().MaterialCode).Sum(x => x.StockQuantity));
                    UploadMesMaterialLotaAcept(model);
                }
                _unitOfWorkManage.CommitTran();
                return WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Inbound.cs
@@ -867,6 +867,12 @@
                {
                    return content.Error($"库存信息已存在");
                }
                Dt_Task task = BaseDal.QueryFirst(x => x.PalletCode == palletCode);
                if(task != null)
                {
                    return content.Error($"托盘{palletCode}已经存在任务,请勿重复下达");
                }
                Dt_PalletTypeInfo palletTypeInfo = _palletTypeInfoRepository.QueryFirst(x=>x.CodeStartStr== palletType);
                if (palletTypeInfo == null)
                {
@@ -1143,5 +1149,97 @@
            }
            
        }
        /// <summary>
        /// PP平库申请入库任务
        /// </summary>
        /// <param name="saveModel"></param>
        /// <returns></returns>
        public WebResponseContent PPPKRequestInboundTask(SaveModel saveModel)
        {
            try
            {
                var palletCode = saveModel.MainData["barcode"].ToString();
                var warehouseId = saveModel.MainData["warehouseId"].ObjToInt();
                var stationCode = saveModel.MainData["startPoint"].ToString();
                Dt_Warehouse warehouse = _basicRepository.WarehouseRepository.QueryFirst(x => x.WarehouseId == warehouseId);
                if (warehouse == null)
                {
                    return WebResponseContent.Instance.Error($"未找到库区");
                }
                Dt_Task task = Repository.QueryFirst(x => x.PalletCode == palletCode && x.WarehouseId == warehouseId);
                if (task != null)
                {
                    return WebResponseContent.Instance.Error($"该托盘已生成任务");
                }
                Dt_StockInfo stockInfo = _stockRepository.StockInfoRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == palletCode).Includes(x => x.Details).First();
                if (stockInfo == null)
                {
                    return WebResponseContent.Instance.Error($"未找到组盘信息");
                }
                if (stockInfo.StockStatus != StockStatusEmun.组盘暂存.ObjToInt() && stockInfo.StockStatus != StockStatusEmun.手动组盘暂存.ObjToInt() && stockInfo.StockStatus != StockStatusEmun.拣选完成.ObjToInt() && stockInfo.StockStatus != StockStatusEmun.送检库存完成.ObjToInt() && stockInfo.StockStatus != StockStatusEmun.盘点库存完成.ObjToInt())
                {
                    return WebResponseContent.Instance.Error($"该托盘状态不正确,不可申请入库");
                }
                if (!string.IsNullOrEmpty(stockInfo.LocationCode))
                {
                    return WebResponseContent.Instance.Error($"该托盘已绑定货位");
                }
                if (warehouseId != stockInfo.WarehouseId)
                {
                    return WebResponseContent.Instance.Error($"仓库不正确");
                }
                Dt_LocationInfo? locationInfoPPPK = _basicService.LocationInfoService.AssignLocation("AGV_PP", stockInfo.PalletType, stockInfo.WarehouseId);
                if (locationInfoPPPK == null)
                {
                    return WebResponseContent.Instance.Error($"货位分配失败,未找到可分配货位");
                }
                Dt_Task newTask = new Dt_Task()
                {
                    CurrentAddress = stationCode,
                    Grade = 0,
                    NextAddress = "",
                    PalletCode = palletCode,
                    Roadway = "AGV_PP",
                    SourceAddress = stationCode,
                    TargetAddress = locationInfoPPPK.LocationCode,
                    TaskType = TaskTypeEnum.PPPKInbound.ObjToInt(),
                    TaskStatus = TaskStatusEnum.New.ObjToInt(),
                    WarehouseId = stockInfo.WarehouseId,
                    PalletType = stockInfo.PalletType,
                    MaterielCode = stockInfo.Details?.Where(x => x.StockId == stockInfo.Id).FirstOrDefault()?.MaterielCode,
                    Quantity = (float)stockInfo.Details?.Where(x => x.StockId == stockInfo.Id).Sum(x => x.StockQuantity),
                    BatchNo = stockInfo.Details?.Where(x => x.StockId == stockInfo.Id).FirstOrDefault()?.BatchNo
                };
                if (stockInfo.StockStatus == StockStatusEmun.手动组盘暂存.ObjToInt())
                {
                    stockInfo.StockStatus = StockStatusEmun.手动组盘入库确认.ObjToInt();
                }
                else
                {
                    stockInfo.StockStatus = StockStatusEmun.入库确认.ObjToInt();
                }
                _unitOfWorkManage.BeginTran();
                LocationStatusEnum lastStatusPPorGM = (LocationStatusEnum)locationInfoPPPK.LocationStatus;
                _recordService.LocationStatusChangeRecordSetvice.AddLocationStatusChangeRecord(locationInfoPPPK, lastStatusPPorGM, LocationStatusEnum.Lock, LocationChangeType.InboundAssignLocation);
                _basicService.LocationInfoService.UpdateLocationStatus(locationInfoPPPK, newTask.PalletType, LocationStatusEnum.Lock, newTask.WarehouseId);
                int taskId = BaseDal.AddData(newTask);
                newTask.TaskId = taskId;
                _stockRepository.StockInfoRepository.UpdateData(stockInfo);
                _unitOfWorkManage.CommitTran();
                PushTasksToWCS(new List<Dt_Task> { newTask },"AGV_PP");
                return WebResponseContent.Instance.OK(data: newTask);
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Outbound.cs
@@ -789,7 +789,7 @@
                            NextAddress = "",
                            Roadway = locationInfo.RoadwayNo,
                            SourceAddress = stockInfo.LocationCode,
                            TargetAddress = "",
                            TargetAddress = stockInfo.Remark??"",
                            TaskStatus = TaskStatusEnum.New.ObjToInt(),
                            TaskType = taskType.ObjToInt(),
                            TaskNum = BaseDal.GetTaskNum(nameof(SequenceEnum.SeqTaskNum)),
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Basic/MaterielInfoController.cs
@@ -51,5 +51,24 @@
        {
            return Service.GetWarehouseMaterielInfos(warehouseId);
        }
        /// <summary>
        /// PP平库物料码解析
        /// </summary>
        /// <param name="serNum"></param>
        /// <returns></returns>
        [HttpPost, HttpGet, Route("PPPKCodeAnalysis")]
        public WebResponseContent PPPKCodeAnalysis(string serNum)
        {
            try
            {
                MatSerNumAnalysisModel model = CodeAnalysisHelper.PPPKCodeAnalysis<MatSerNumAnalysisModel>(AnalysisCodeEnum.PPPKSerNumAnalysis, serNum);
                return WebResponseContent.Instance.OK(data: model);
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs
@@ -118,5 +118,19 @@
        {
            return Service.MaterielGroup(palletCode, initiallife, warehouseId, serNums);
        }
        /// <summary>
        /// æ— å…¥åº“单组盘
        /// </summary>
        /// <param name="palletCode"></param>
        /// <param name="initiallife"></param>
        /// <param name="warehouseId"></param>
        /// <param name="serNums"></param>
        /// <returns></returns>
        [HttpPost, HttpGet, Route("PPPKManualMaterielGroup")]
        public WebResponseContent PPPKMaterielGroup(string palletCode, int initiallife, int warehouseId, [FromBody] List<string> serNums)
        {
            return Service.PPPKMaterielGroup(palletCode, initiallife, warehouseId, serNums);
        }
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/MES/MesController.cs
@@ -301,5 +301,17 @@
            }
            return MesResponseContent.Instance.OK("成功");
        }
        /// <summary>
        /// ç”Ÿæˆå¹³åº“搬运任务
        /// </summary>
        /// <param name="orderDetailId"></param>
        /// <param name="stockSelectViews"></param>
        /// <returns></returns>
        [HttpPost, HttpGet, Route("PPTaskMove"), AllowAnonymous]
        public WebResponseContent PPTaskMove(string palletCode, string startPoint, int warehouseId, [FromBody] List<string> serNums)
        {
            return _taskService.PPTaskMove(palletCode, startPoint,warehouseId,serNums);
        }
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/TaskInfo/TaskController.cs
@@ -429,5 +429,16 @@
        {
            return await Service.TaskHandCancel(taskNum);
        }
        /// <summary>
        /// PP申请入库任务
        /// </summary>
        /// <param name="saveModel"></param>
        /// <returns></returns>
        [HttpPost, HttpGet, Route("PPPKRequestInboundTask"), AllowAnonymous]
        public WebResponseContent PPPKRequestInboundTask([FromBody] SaveModel saveModel)
        {
            return Service.PPPKRequestInboundTask(saveModel);
        }
    }
}
´úÂë¹ÜÀí/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Filter/CustomProfile.cs
@@ -42,6 +42,8 @@
            CreateMap<ErpProductWarehousingOrderDTO, Dt_ErpProInOrder>().ForMember(x => x.ProSaleOrderNo, b => b.MapFrom(b => b.SaleOrder)).ForMember(x => x.Remark, b => b.MapFrom(b => b.Note)).ForMember(x => x.UpperOrderNo, b => b.MapFrom(b => b.TransferNo)).ForMember(x => x.ProStockAttribute, b => b.MapFrom(b => ProStockAttributeEnum.成品.ObjToInt())).ForMember(x => x.ProInStatus, b => b.MapFrom(b => InOrderStatusEnum.未开始.ObjToInt()));
            CreateMap<ErpProductTransferOrderDTO, Dt_ErpProTransferOrder>().ForMember(x => x.ProSaleOrderNo, b => b.MapFrom(b => b.SaleOrder)).ForMember(x => x.Remark, b => b.MapFrom(b => b.Note)).ForMember(x => x.UpperOrderNo, b => b.MapFrom(b => b.TransferNo)).ForMember(x => x.OrderType, b => b.MapFrom(b => ErpProOutTypeEnum.ProOutAllocat.ObjToInt())).ForMember(x => x.ProStockAttribute, b => b.MapFrom(b => ProStockAttributeEnum.研发.ObjToInt()));
            CreateMap<ErpProOutLingOrder, Dt_ProCollectOutOrderDetail>().ForMember(x => x.ProOrderDetailStatus, b => b.MapFrom(b => 0)).ForMember(x => x.OverQtyPcs, b => b.MapFrom(b => 0)).ForMember(x => x.LockQtyPcs, b => b.MapFrom(b => 0));
            CreateMap<MaterialDetail, Dt_MesPPCutOutboundOrderDetail>().ForMember(x => x.OrderDetailStatus, b => b.MapFrom(b => 0)).ForMember(x => x.OrderQuantity, b => b.MapFrom(b => b.RequiredQuantity));
        }
    }
}
´úÂë¹ÜÀí/»´°²PDA/pages/stash/PPPKboxing.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,517 @@
<template>
    <view class="page-container">
        <!-- é¡¶éƒ¨å¯¼èˆªæ  -->
        <view class="nav-header">
            <uni-segmented-control
                :current="current"
                :values="items"
                @clickItem="onClickItem"
                class="segmented-control"
            >
            </uni-segmented-control>
        </view>
        <!-- ä¸»å†…容区 -->
        <view class="main-content">
            <!-- ç»„盘模块 -->
            <view v-if="current === 0" class="card-container">
                <!-- ç»„盘表单卡片 -->
                <view class="form-card">
                    <uni-forms class="form-wrapper" label-width="80px">
                        <uni-forms-item label="托盘条码:" class="form-item">
                            <uni-easyinput
                                type="text"
                                placeholder="请扫描托盘条码"
                                :focus="barcodeFocus"
                                v-model="barcode"
                                @confirm="onBarcodeConfirm"
                                class="input-field"
                                :disabled="isSubmitting"
                            />
                        </uni-forms-item>
                        <uni-forms-item label="内箱标签:" class="form-item">
                            <uni-easyinput
                                type="text"
                                placeholder="请扫描内箱标签"
                                :focus="materSnFocus"
                                v-model="materSn"
                                @confirm="onMaterSnConfirm"
                                class="input-field"
                                :disabled="isSubmitting"
                            />
                        </uni-forms-item>
                        <uni-forms-item :label="Testlabel" v-if="Test" class="form-item">
                            <uni-easyinput
                                type="text"
                                :placeholder="Testplaceholder"
                                v-model="Initiallife"
                                class="input-field"
                                :disabled="isSubmitting"
                            />
                        </uni-forms-item>
                        <view class="form-actions">
                            <button
                                @click="submit"
                                type="primary"
                                class="btn-primary"
                                :disabled="isSubmitting"
                            >
                                <uni-icons type="refresh" size="16" v-if="isSubmitting"></uni-icons>
                                {{isSubmitting ? '组盘中...' : '组盘'}}
                            </button>
                        </view>
                    </uni-forms>
                </view>
                <!-- ç‰©æ–™ä¿¡æ¯åˆ—表 -->
                <view class="list-card" v-if="matInfos.length > 0">
                    <view class="list-header">
                        <text class="list-title">物料信息</text>
                        <text class="count-badge">1</text>
                    </view>
                    <uni-list class="material-list">
                        <uni-list-item
                            direction="column"
                            v-for="(item,index) in matInfos"
                            :key="index"
                            class="list-item"
                        >
                            <template v-slot:body>
                                <view class="list-item-content">
                                    <uni-icons
                                        type="trash"
                                        size="20"
                                        class="delete-icon"
                                        @click="deleteList(index)"
                                        :disabled="isSubmitting"
                                    >
                                    </uni-icons>
                                    <view class="info-grid">
                                        <view class="info-row">
                                            <text class="label">采购单号:</text>
                                            <text class="value">{{item.purchaseOrderNo}}</text>
                                        </view>
                                        <view class="info-row">
                                            <text class="label">物料编码:</text>
                                            <text class="value">{{item.materielCode}}</text>
                                        </view>
                                        <view class="info-row">
                                            <text class="label">批次号:</text>
                                            <text class="value">{{item.lotNo}}</text>
                                        </view>
                                        <view class="info-row">
                                            <text class="label">数量:</text>
                                            <text class="value">{{item.quantity}}</text>
                                        </view>
                                        <view class="info-row">
                                            <text class="label">生产日期:</text>
                                            <text class="value">{{item.productionDate}}</text>
                                        </view>
                                        <view class="info-row">
                                            <text class="label">有效期:</text>
                                            <text class="value">{{item.effectiveDate}}</text>
                                        </view>
                                        <view class="info-row">
                                            <text class="label">物料长度:</text>
                                            <text class="value">{{item.materielLength}}</text>
                                        </view>
                                    </view>
                                </view>
                            </template>
                        </uni-list-item>
                    </uni-list>
                </view>
                <!-- ç©ºçŠ¶æ€æç¤º -->
                <view class="empty-state" v-if="matInfos.length === 0 && barcode">
                    <uni-icons type="empty" size="60" color="#ccc"></uni-icons>
                    <text class="empty-text">暂无物料信息,请扫描内箱标签</text>
                </view>
            </view>
            <!-- å…¥åº“模块(保持不变) -->
            <view v-if="current === 1" class="card-container">
                <view class="form-card">
                    <uni-forms class="form-wrapper" label-width="80px">
                        <uni-forms-item label="托盘条码:" class="form-item">
                            <uni-easyinput
                                type="text"
                                placeholder="请扫描托盘条码"
                                :focus="!addressFocus"
                                v-model="inboundBarcode"
                                @confirm="inputChangebarcode"
                                class="input-field"
                                :disabled="isInboundSubmitting"
                            />
                        </uni-forms-item>
                        <uni-forms-item label="地址条码:" class="form-item">
                            <uni-easyinput
                                type="text"
                                placeholder="请扫描地址条码"
                                :focus="addressFocus"
                                v-model="address"
                                class="input-field"
                                :disabled="addressdisabled || isInboundSubmitting"
                            />
                        </uni-forms-item>
                        <view class="form-actions">
                            <button
                                @click="inbound"
                                type="primary"
                                class="btn-primary"
                                :disabled="isInboundSubmitting"
                            >
                                <uni-icons type="refresh" size="16" v-if="isInboundSubmitting"></uni-icons>
                                {{isInboundSubmitting ? '入库中...' : '入库确认'}}
                            </button>
                        </view>
                    </uni-forms>
                </view>
                <view class="list-card" v-if="inboundBarcode">
                    <view class="summary-card" v-if="Summmary > 0">
                        <text class="summary-label">组盘总数量:</text>
                        <text class="summary-value">{{Summmary}}</text>
                    </view>
                    <uni-list class="material-list" v-if="stockInfoDetail.length > 0">
                        <uni-list-item direction="column" v-for="(item,index) in stockInfoDetail" :key="index">
                            <template v-slot:body>
                                <view class="list-item-content">
                                    <view class="info-grid">
                                        <view class="info-row"><text class="label">物料编号:</text><text class="value">{{item.materielCode}}</text></view>
                                        <view class="info-row"><text class="label">物料名称:</text><text class="value">{{item.materielName}}</text></view>
                                        <view class="info-row"><text class="label">物料批次:</text><text class="value">{{item.batchNo}}</text></view>
                                        <view class="info-row"><text class="label">组盘数量:</text><text class="value">{{item.stockQuantity}}</text></view>
                                        <view class="info-row"><text class="label">生产日期:</text><text class="value">{{item.productionDate}}</text></view>
                                        <view class="info-row"><text class="label">有效期:</text><text class="value">{{item.effectiveDate}}</text></view>
                                    </view>
                                </view>
                            </template>
                        </uni-list-item>
                    </uni-list>
                </view>
            </view>
        </view>
        <u-toast ref="uToast" />
    </view>
</template>
<script>
    const innerAudioContext = uni.createInnerAudioContext();
    export default {
        data() {
            return {
                items: ['组盘', '入库'],
                current: 0,
                // ç»„盘模块数据
                matInfos: [],
                orderNo: "",
                barcode: "",
                materSn: "",
                Initiallife: 1000,
                sns: [],
                // ç»„盘焦点控制
                barcodeFocus: true,   // æ‰˜ç›˜æ¡ç åˆå§‹èŽ·å¾—ç„¦ç‚¹
                materSnFocus: false,  // å†…箱标签焦点
                // å…¥åº“模块数据
                addressFocus: false,
                inboundBarcode: "",
                address: "",
                warehouseId: "",
                Test: false,
                Testlabel: "",
                Testplaceholder: "",
                Testcheck: false,
                Summmary: 0,
                stockInfoDetail: [],
                addressdisabled: false,
                isSubmitting: false,
                isInboundSubmitting: false
            }
        },
        onLoad(res) {
            this.orderNo = res.orderNo;
            this.warehouseId = res.warehouseId;
            if (this.warehouseId == 6) {
                this.Test = true;
                this.Testlabel = "初始寿命:";
                this.Testplaceholder = "请输入初始寿命";
            } else if (this.warehouseId == 2) {
                this.Test = true;
                this.Testlabel = "数量:";
                this.Testplaceholder = "请输入数量";
                this.Initiallife = 16;
            } else if (this.warehouseId == 3) {
                this.address = "1011";
                this.addressdisabled = true;
            }
            // ç¡®ä¿åˆå§‹ç„¦ç‚¹åœ¨æ‰˜ç›˜æ¡ç 
            this.barcodeFocus = true;
            this.materSnFocus = false;
        },
        methods: {
            getData() {},
            onClickItem(e) {
                this.current = e.currentIndex;
                // åˆ‡æ¢é€‰é¡¹å¡æ—¶é‡ç½®ç„¦ç‚¹
                if (this.current === 0) {
                    this.barcodeFocus = true;
                    this.materSnFocus = false;
                } else {
                    this.addressFocus = false;
                }
            },
            // ==================== ç»„盘模块焦点跳转 ====================
            /**
             * æ‰˜ç›˜æ¡ç æ‰«æç¡®è®¤
             * æ‰«æåŽè‡ªåŠ¨è·³è½¬åˆ°å†…ç®±æ ‡ç­¾è¾“å…¥æ¡†
             */
            onBarcodeConfirm() {
                if (!this.barcode || this.barcode.trim() === '') {
                    this.$refs.uToast.show({
                        title: "请扫描托盘条码",
                        type: 'error'
                    });
                    // ä¿æŒç„¦ç‚¹åœ¨æ‰˜ç›˜æ¡ç æ¡†
                    this.barcodeFocus = true;
                    this.materSnFocus = false;
                    return;
                }
                // æ‰˜ç›˜ç æœ‰æ•ˆï¼Œè·³è½¬åˆ°å†…箱标签
                this.barcodeFocus = false;
                this.materSnFocus = true;
            },
            /**
             * å†…箱标签扫描确认
             * è‡ªåŠ¨è§£æžå†…ç®±ç ï¼Œæ¸…ç©ºè¾“å…¥æ¡†ï¼Œç„¦ç‚¹ä¿ç•™åœ¨å†…ç®±æ ‡ç­¾æ¡†
             */
            onMaterSnConfirm() {
                if (!this.materSn || this.materSn.trim() === '') {
                    this.$refs.uToast.show({
                        title: "请扫描内箱标签",
                        type: 'error'
                    });
                    return;
                }
                // ç‰¹æ®Šå¤„理:仓库11时去掉后缀
                let snToProcess = this.materSn;
                if (this.warehouseId == 11) {
                    snToProcess = snToProcess.replace(/,SC.*/, '');
                }
                // å†…箱码格式校验(必须包含7个字段,以逗号分隔)
                if (snToProcess.split(',').length != 7) {
                    this.$refs.uToast.show({
                        title: "内箱码格式错误,请重新扫描",
                        type: 'error'
                    });
                    // æ¸…空输入框,便于重新扫描
                    this.materSn = "";
                    // ç„¦ç‚¹ä¸åŠ¨ï¼ˆmaterSnFocus å·²æ˜¯ true)
                    return;
                }
                // å‘起后端解析请求
                this.$u.post('/api/MaterielInfo/PPPKCodeAnalysis?serNum=' + snToProcess, {})
                    .then(res => {
                        if (res.status) {
                            // è§£æžæˆåŠŸï¼šæ›¿æ¢ä¸ºæœ€æ–°çš„å†…ç®±ç ï¼ˆåªä¿ç•™ä¸€ä¸ªï¼‰
                            this.sns = [res.data.serialNumber];
                            this.matInfos = [res.data];
                            this.$refs.uToast.show({
                                title: "内箱码已更新",
                                type: "success",
                                duration: 1500
                            });
                            // æ¸…空输入框,为下一次扫描做准备(焦点仍在内箱码框)
                            this.materSn = "";
                            // ç„¦ç‚¹ä¸åŠ¨ï¼Œä¿æŒåœ¨å†…ç®±ç æ¡†ï¼ˆmaterSnFocus å·²æ˜¯ true)
                        } else {
                            this.$refs.uToast.show({
                                title: res.message,
                                type: "error"
                            });
                            // è§£æžå¤±è´¥ï¼Œæ¸…空输入框,让用户重新扫描
                            this.materSn = "";
                        }
                    })
                    .catch(err => {
                        this.$refs.uToast.show({
                            title: err.message || "解析失败",
                            type: "error"
                        });
                        this.materSn = "";
                    });
            },
            // åˆ é™¤å†…箱码(清空)
            deleteList() {
                if (this.isSubmitting) return;
                this.matInfos = [];
                this.sns = [];
                this.$refs.uToast.show({
                    title: "内箱码已清空",
                    type: "info"
                });
                // ç„¦ç‚¹ä¿ç•™åœ¨å†…箱码框
            },
            // ==================== ç»„盘提交 ====================
            submit() {
                if (this.isSubmitting) return;
                if (!this.barcode) {
                    this.$refs.uToast.show({ title: "请扫描托盘条码", type: 'error' });
                    this.resetFocusToBarcode();
                    return;
                }
                if (this.matInfos.length === 0) {
                    this.$refs.uToast.show({ title: "请扫描内箱标签", type: 'error' });
                    this.resetFocusToMaterSn();
                    return;
                }
                if (this.Test && !this.Testcheck) {
                    this.Testcheck = true;
                    this.$refs.uToast.show({
                        title: this.warehouseId == 2 ? "请确认数量" : "请确认初始寿命",
                        type: 'error'
                    });
                    return;
                }
                if (this.warehouseId == 2) {
                    let sn = this.sns[0];
                    this.sns = Array(this.Initiallife).fill(sn);
                }
                this.isSubmitting = true;
                let url = `palletCode=${this.barcode}&initiallife=${this.Initiallife}&warehouseId=${this.warehouseId}`;
                this.$u.post('/api/InboundOrder/PPPKManualMaterielGroup?' + url, this.sns)
                    .then(res => {
                        if (res.status) {
                            this.$refs.uToast.show({ title: "组盘成功", type: "success" });
                            // é‡ç½®è¡¨å•
                            this.barcode = "";
                            this.matInfos = [];
                            this.sns = [];
                            // é‡ç½®ç„¦ç‚¹ï¼šå›žåˆ°æ‰˜ç›˜æ¡ç æ¡†ï¼Œå¼€å§‹æ–°çš„一轮
                            this.resetFocusToBarcode();
                        } else {
                            this.$refs.uToast.show({ title: res.message, type: "error" });
                        }
                    })
                    .finally(() => {
                        this.isSubmitting = false;
                    });
            },
            // ==================== ç„¦ç‚¹é‡ç½®è¾…助 ====================
            resetFocusToBarcode() {
                this.barcodeFocus = true;
                this.materSnFocus = false;
            },
            resetFocusToMaterSn() {
                this.barcodeFocus = false;
                this.materSnFocus = true;
            },
            // ==================== å…¥åº“模块(保持原逻辑) ====================
            inputChangebarcode() {
                this.addressFocus = false;
                this.$nextTick(() => {
                    if (!this.inboundBarcode) return;
                    this.addressFocus = true;
                    this.$u.post('/api/StockInfo/StockQueryData', {
                        MainData: { barcode: this.inboundBarcode, warehouseId: this.warehouseId }
                    }).then(res => {
                        this.stockInfoDetail = [];
                        this.Summmary = 0;
                        if (res.status) {
                            this.stockInfoDetail = res.data.details;
                            this.stockInfoDetail.forEach(item => {
                                this.Summmary += item.stockQuantity;
                            });
                        } else {
                            this.$refs.uToast.show({ title: res.message, type: "error" });
                        }
                    })
                })
            },
            inbound() {
                if (this.isInboundSubmitting) return;
                if (!this.inboundBarcode) {
                    this.$refs.uToast.show({ title: "请扫描托盘条码", type: "error" });
                    return;
                }
                if (!this.address) {
                    this.$refs.uToast.show({ title: "请扫描地址条码", type: "error" });
                    return;
                }
                this.isInboundSubmitting = true;
                this.$u.post('/api/Task/PPPKRequestInboundTask', {
                    MainData: {
                        barcode: this.inboundBarcode,
                        startPoint: this.address,
                        warehouseId: this.warehouseId
                    }
                }).then(res => {
                    if (res.status) {
                        this.inboundBarcode = "";
                        if (this.warehouseId != 3) this.address = "";
                        this.stockInfoDetail = [];
                        this.Summmary = 0;
                        this.$refs.uToast.show({ title: "入库成功", type: "success" });
                    } else {
                        this.$refs.uToast.show({ title: res.message, type: "error" });
                    }
                }).finally(() => {
                    this.isInboundSubmitting = false;
                });
            }
        }
    }
</script>
<style lang="scss">
    @import '@/common/uni-ui.scss';
    page { background-color: #f5f7fa; font-size: 14px; color: #333; }
    .page-container { min-height: 100vh; display: flex; flex-direction: column; }
    .nav-header { background: #fff; padding: 12px 16px; box-shadow: 0 2px 8px rgba(0,0,0,0.05); }
    .segmented-control { border-radius: 8px; --uni-segmented-control-height: 40px; }
    .main-content { flex: 1; padding: 16px; }
    .card-container { display: flex; flex-direction: column; gap: 16px; }
    .form-card { background: #fff; border-radius: 12px; padding: 20px; box-shadow: 0 2px 12px rgba(0,0,0,0.04); }
    .form-item { margin-bottom: 16px; }
    .input-field { border-radius: 8px; height: 44px; }
    .form-actions { margin-top: 10px; }
    .btn-primary { width: 100%; height: 48px; border-radius: 8px; }
    .list-card { background: #fff; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 12px rgba(0,0,0,0.04); }
    .list-header { padding: 16px; border-bottom: 1px solid #f0f0f0; display: flex; justify-content: space-between; }
    .count-badge { background: #e6f4ff; color: #165dff; padding: 2px 8px; border-radius: 20px; font-size: 12px; }
    .list-item-content { position: relative; padding: 16px; }
    .delete-icon { position: absolute; right: 16px; top: 50%; transform: translateY(-50%); color: #ef4444; }
    .info-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 12px; }
    .info-row { display: flex; flex-direction: column; }
    .label { font-size: 12px; color: #6b7280; }
    .value { font-size: 14px; color: #222; font-weight: 500; }
    .summary-card { padding: 16px; background: #e6f4ff; font-size: 15px; }
    .summary-value { font-weight: bold; color: #165dff; margin-left: 6px; }
    .empty-state { padding: 50px 20px; text-align: center; color: #999; }
</style>
´úÂë¹ÜÀí/»´°²PDA/pages/stash/PPTaskMove.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,727 @@
<template>
    <view class="page-container">
        <!-- é¡¶éƒ¨å¯¼èˆªæ  -->
        <view class="nav-header">
            <uni-segmented-control
                :current="current"
                :values="items"
                @clickItem="onClickItem"
                class="segmented-control"
            >
            </uni-segmented-control>
        </view>
        <!-- ä¸»å†…容区 -->
        <view class="main-content">
            <!-- ç”ŸæˆPP搬运任务模块 -->
            <view v-if="current === 0" class="card-container">
                <!-- è¡¨å•卡片 -->
                <view class="form-card">
                    <uni-forms class="form-wrapper" label-width="80px">
                        <!-- æ‰˜ç›˜æ¡ç è¾“入框:初始获得焦点,扫描后自动跳转到起始地址 -->
                        <uni-forms-item label="托盘条码:" class="form-item">
                            <uni-easyinput
                                type="text"
                                placeholder="请扫描托盘条码"
                                :focus="barcodeFocus"
                                v-model="barcode"
                                @confirm="onBarcodeConfirm"
                                class="input-field"
                            />
                        </uni-forms-item>
                        <!-- èµ·å§‹åœ°å€æ‰«ææ¡†ï¼šæ‰˜ç›˜ç æ‰«æåŽè‡ªåŠ¨èšç„¦ï¼Œæ‰«æåŽè·³è½¬åˆ°å†…ç®±ç  -->
                        <uni-forms-item label="起始地址:" class="form-item">
                            <uni-easyinput
                                type="text"
                                placeholder="请扫描起始地址"
                                :focus="startPointFocus"
                                v-model="startPoint"
                                @confirm="onStartPointConfirm"
                                class="input-field"
                            />
                        </uni-forms-item>
                        <!-- å†…箱标签输入框:起始地址扫描后自动聚焦,扫描后触发后端解析,不自动跳转 -->
                        <uni-forms-item label="内箱标签:" class="form-item">
                            <uni-easyinput
                                type="text"
                                placeholder="请扫描内箱标签"
                                :focus="materSnFocus"
                                v-model="materSn"
                                @confirm="onMaterSnConfirm"
                                class="input-field"
                            />
                            <!-- å·²é€‰å†…箱码提示 -->
                            <view class="selected-tip" v-if="matInfos.length > 0">
                                <text class="tip-text">当前已选:</text>
                                <text class="sn-text">{{matInfos[0].serialNumber || matInfos[0].materielCode}}</text>
                                <uni-icons type="clear" size="14" class="clear-icon" @click="clearSn"></uni-icons>
                            </view>
                        </uni-forms-item>
                        <!-- ç‰¹æ®Šä»“库字段(测试架/油墨) -->
                        <uni-forms-item :label="Testlabel" v-if="Test" class="form-item">
                            <uni-easyinput
                                type="text"
                                :placeholder="Testplaceholder"
                                v-model="Initiallife"
                                class="input-field"
                            />
                        </uni-forms-item>
                        <view class="form-actions">
                            <button
                                @click="generatePPTask"
                                type="primary"
                                class="btn-primary"
                                :disabled="isSubmitting"
                            >
                                <uni-icons type="refresh" size="16" v-if="isSubmitting"></uni-icons>
                                {{isSubmitting ? '生成中...' : '生成PP搬运任务'}}
                            </button>
                        </view>
                    </uni-forms>
                </view>
                <!-- åˆ—表卡片:展示内箱码物料信息 -->
                <view class="list-card" v-if="matInfos.length > 0">
                    <view class="list-header">
                        <text class="list-title">物料信息</text>
                        <text class="count-badge">1</text>
                    </view>
                    <uni-list class="material-list">
                        <uni-list-item
                            direction="column"
                            v-for="(item,index) in matInfos"
                            :key="index"
                            class="list-item"
                        >
                            <template v-slot:body>
                                <view class="list-item-content">
                                    <uni-icons
                                        type="trash"
                                        size="20"
                                        class="delete-icon"
                                        @click="deleteList(index)"
                                    >
                                    </uni-icons>
                                    <view class="info-grid">
                                        <view class="info-row">
                                            <text class="label">采购单号:</text>
                                            <text class="value">{{item.purchaseOrderNo}}</text>
                                        </view>
                                        <view class="info-row">
                                            <text class="label">物料编码:</text>
                                            <text class="value">{{item.materielCode}}</text>
                                        </view>
                                        <view class="info-row">
                                            <text class="label">批次号:</text>
                                            <text class="value">{{item.lotNo}}</text>
                                        </view>
                                        <view class="info-row">
                                            <text class="label">数量:</text>
                                            <text class="value">{{item.quantity}}</text>
                                        </view>
                                        <view class="info-row">
                                            <text class="label">生产日期:</text>
                                            <text class="value">{{item.productionDate}}</text>
                                        </view>
                                        <view class="info-row">
                                            <text class="label">有效期:</text>
                                            <text class="value">{{item.effectiveDate}}</text>
                                        </view>
                                        <view class="info-row">
                                            <text class="label">物料长度:</text>
                                            <text class="value">{{item.materielLength}}</text>
                                        </view>
                                    </view>
                                </view>
                            </template>
                        </uni-list-item>
                    </uni-list>
                </view>
                <!-- ç©ºçŠ¶æ€æç¤º -->
                <view class="empty-state" v-if="matInfos.length === 0 && barcode">
                    <uni-icons type="empty" size="60" color="#ccc"></uni-icons>
                    <text class="empty-text">暂无物料信息,请扫描内箱标签</text>
                </view>
            </view>
        </view>
        <u-toast ref="uToast" />
    </view>
</template>
<script>
    const innerAudioContext = uni.createInnerAudioContext();
    export default {
        data() {
            return {
                // æ ‡ç­¾é¡µé…ç½®
                items: ['生成PP搬运任务'],
                current: 0,
                // è¡¨å•数据
                barcode: "",           // æ‰˜ç›˜æ¡ç 
                startPoint: "",        // èµ·å§‹åœ°å€
                materSn: "",           // å†…箱标签原始输入
                Initiallife: 1000,     // ç‰¹æ®Šä»“库字段(寿命/数量)
                // å†…箱码解析结果
                matInfos: [],          // ç‰©æ–™ä¿¡æ¯ï¼ˆå½“前仅保留一条)
                sns: [],               // åºåˆ—号数组(用于提交)
                // ç„¦ç‚¹æŽ§åˆ¶ï¼ˆå®žçްPDA扫描自动跳转)
                barcodeFocus: true,    // æ‰˜ç›˜æ¡ç è¾“入框焦点
                startPointFocus: false,// èµ·å§‹åœ°å€è¾“入框焦点
                materSnFocus: false,   // å†…箱标签输入框焦点
                // ç‰¹æ®Šä»“库标识
                Test: false,
                Testlabel: "",
                Testplaceholder: "",
                Testcheck: false,
                // å…¶ä»–辅助数据
                orderNo: "",
                warehouseId: "",
                orderInfo: [],
                // é˜²é‡å¤æäº¤æ ‡è¯†
                isSubmitting: false
            }
        },
        onLoad(res) {
            // æŽ¥æ”¶é¡µé¢å‚æ•°
            this.orderNo = res.orderNo;
            this.warehouseId = res.warehouseId;
            // ç‰¹æ®Šä»“库逻辑:测试架仓库(6) æˆ– æ²¹å¢¨ä»“库(2)
            if (this.warehouseId == 6) {
                this.Test = true;
                this.Testlabel = "初始寿命:";
                this.Testplaceholder = "请输入初始寿命";
            } else if (this.warehouseId == 2) {
                this.Test = true;
                this.Testlabel = "数量:";
                this.Testplaceholder = "请输入数量";
                this.Initiallife = 16;
            }
            // åŠ è½½å•æ®ä¿¡æ¯
            this.getData();
        },
        onReady() {
            // ç¡®ä¿é¡µé¢åŠ è½½åŽæ‰˜ç›˜ç è¾“å…¥æ¡†èŽ·å¾—ç„¦ç‚¹ï¼ˆPDA自动聚焦)
            this.barcodeFocus = true;
            this.startPointFocus = false;
            this.materSnFocus = false;
        },
        methods: {
            // ==================== æ•°æ®èŽ·å– ====================
            getData() {
                var postData = {
                    MainData: {
                        orderNo: this.orderNo
                    },
                }
                this.$u.post('/api/InboundOrderDetail/GetInboundOrderDetails', postData).then((res) => {
                    if (res.status) {
                        this.orderInfo = res.data;
                    }
                })
            },
            // ==================== æ ‡ç­¾é¡µåˆ‡æ¢ ====================
            onClickItem(e) {
                if (this.current !== e.currentIndex) {
                    this.current = e.currentIndex;
                }
            },
            // ==================== ç„¦ç‚¹è·³è½¬æ ¸å¿ƒé€»è¾‘ ====================
            /**
             * æ‰˜ç›˜æ¡ç æ‰«æç¡®è®¤
             * PDA扫描后自动回车触发,校验非空后跳转焦点到起始地址
             */
            onBarcodeConfirm() {
                if (!this.barcode || this.barcode.trim() === '') {
                    this.$refs.uToast.show({
                        title: "请扫描托盘条码",
                        type: 'error'
                    });
                    // ä¿æŒç„¦ç‚¹åœ¨æ‰˜ç›˜æ¡ç æ¡†ï¼Œç­‰å¾…重新扫描
                    this.barcodeFocus = true;
                    this.startPointFocus = false;
                    this.materSnFocus = false;
                    return;
                }
                // æ‰˜ç›˜ç æœ‰æ•ˆï¼Œè·³è½¬ç„¦ç‚¹åˆ°èµ·å§‹åœ°å€è¾“入框
                this.barcodeFocus = false;
                this.startPointFocus = true;
                this.materSnFocus = false;
            },
            /**
             * èµ·å§‹åœ°å€æ‰«æç¡®è®¤
             * PDA扫描后自动回车触发,校验非空后跳转焦点到内箱标签
             */
            onStartPointConfirm() {
                if (!this.startPoint || this.startPoint.trim() === '') {
                    this.$refs.uToast.show({
                        title: "请扫描起始地址",
                        type: 'error'
                    });
                    // ä¿æŒç„¦ç‚¹åœ¨èµ·å§‹åœ°å€æ¡†
                    this.barcodeFocus = false;
                    this.startPointFocus = true;
                    this.materSnFocus = false;
                    return;
                }
                // èµ·å§‹åœ°å€æœ‰æ•ˆï¼Œè·³è½¬ç„¦ç‚¹åˆ°å†…箱标签输入框
                this.barcodeFocus = false;
                this.startPointFocus = false;
                this.materSnFocus = true;
            },
            /**
             * å†…箱标签扫描确认
             * PDA扫描后自动回车触发,解析内箱码,不自动跳转焦点(停留在内箱码框,方便覆盖扫描)
             * æ³¨æ„ï¼šå¿…须等待输入框内容完整后回车才触发,符合PDA扫描习惯
             */
            onMaterSnConfirm() {
                if (!this.materSn || this.materSn.trim() === '') {
                    this.$refs.uToast.show({
                        title: "请扫描内箱标签",
                        type: 'error'
                    });
                    // ä¿æŒç„¦ç‚¹åœ¨å†…箱码框
                    return;
                }
                // ç‰¹æ®Šå¤„理:仓库11时去掉后缀
                let snToProcess = this.materSn;
                if (this.warehouseId == 11) {
                    snToProcess = snToProcess.replace(/,SC.*/, '');
                }
                // å†…箱码格式校验(必须包含7个字段,以逗号分隔)
                if (snToProcess.split(',').length != 7) {
                    this.$refs.uToast.show({
                        title: "内箱码格式错误,请重新扫描",
                        type: 'error'
                    });
                    // æ¸…空输入框,便于重新扫描
                    this.materSn = "";
                    // ä¿æŒç„¦ç‚¹
                    return;
                }
                // å‘起后端解析请求
                this.$u.post('/api/MaterielInfo/PPPKCodeAnalysis?serNum=' + snToProcess, {})
                    .then(res => {
                        if (res.status) {
                            // è§£æžæˆåŠŸï¼šæ›¿æ¢ä¸ºæœ€æ–°çš„å†…ç®±ç ï¼ˆåªä¿ç•™ä¸€ä¸ªï¼‰
                            this.sns = [res.data.serialNumber];
                            this.matInfos = [res.data];
                            this.$refs.uToast.show({
                                title: "内箱码已更新",
                                type: "success",
                                duration: 1500
                            });
                            // æ¸…空输入框,为下一次扫描做准备(焦点仍在内箱码框)
                            this.materSn = "";
                            // ç„¦ç‚¹ä¸åŠ¨ï¼Œä¿æŒåœ¨å†…ç®±ç æ¡†ï¼ˆmaterSnFocus å·²æ˜¯ true)
                        } else {
                            this.$refs.uToast.show({
                                title: res.message,
                                type: "error"
                            });
                            // è§£æžå¤±è´¥ï¼Œæ¸…空输入框,让用户重新扫描
                            this.materSn = "";
                        }
                    })
                    .catch(err => {
                        this.$refs.uToast.show({
                            title: err.message || "解析失败",
                            type: "error"
                        });
                        this.materSn = "";
                    });
            },
            // ==================== è¾…助操作 ====================
            /**
             * æ¸…空当前内箱码数据
             */
            clearSn() {
                this.matInfos = [];
                this.sns = [];
                this.materSn = "";
                this.$refs.uToast.show({
                    title: "内箱码已清空",
                    type: "info"
                });
                // æ¸…空后焦点仍可留在内箱码框,方便重新扫描(不跳转)
            },
            /**
             * åˆ é™¤åˆ—表项(实际也是清空内箱码)
             */
            deleteList(index) {
                this.matInfos = [];
                this.sns = [];
                this.materSn = "";
                this.$refs.uToast.show({
                    title: "内箱码已移除",
                    type: "info"
                });
            },
            // ==================== ç”ŸæˆPP搬运任务 ====================
            generatePPTask() {
                // åŸºç¡€æ ¡éªŒ
                if (!this.barcode) {
                    this.$refs.uToast.show({
                        title: "请扫描托盘条码",
                        type: 'error'
                    });
                    // ç„¦ç‚¹è·³è½¬åˆ°æ‰˜ç›˜æ¡ç æ¡†
                    this.resetFocusToBarcode();
                    return;
                }
                if (!this.startPoint) {
                    this.$refs.uToast.show({
                        title: "请扫描起始地址",
                        type: 'error'
                    });
                    this.resetFocusToStartPoint();
                    return;
                }
                if (this.matInfos.length === 0) {
                    this.$refs.uToast.show({
                        title: "请扫描内箱标签",
                        type: 'error'
                    });
                    this.resetFocusToMaterSn();
                    return;
                }
                // ç‰¹æ®Šä»“库字段校验(测试架/油墨)
                if (this.Test) {
                    if (!this.Testcheck) {
                        this.Testcheck = true;
                        if (this.warehouseId == 2) {
                            this.$refs.uToast.show({
                                title: "请确认数量",
                                type: 'error'
                            });
                        } else if (this.warehouseId == 6) {
                            this.$refs.uToast.show({
                                title: "请确认初始寿命",
                                type: 'error'
                            });
                        }
                        return;
                    }
                }
                // æ²¹å¢¨ä»“库数量处理:复制序列号
                if (this.warehouseId == 2) {
                    const baseSn = this.sns[0];
                    for (let i = 0; i < this.Initiallife - 1; i++) {
                        this.sns.push(baseSn);
                    }
                }
                // é˜²é‡å¤æäº¤
                if (this.isSubmitting) return;
                this.isSubmitting = true;
                // æäº¤ä»»åŠ¡
                let url = 'palletCode=' + this.barcode + '&startPoint=' + this.startPoint + '&warehouseId=' + this.warehouseId;
                this.$u.post('/api/Mes/PPTaskMove?' + url, this.sns)
                    .then(res => {
                        this.Testcheck = false;
                        if (res.status) {
                            this.$refs.uToast.show({
                                title: "PP搬运任务生成成功",
                                type: "success"
                            });
                            // é‡ç½®è¡¨å•所有数据
                            this.barcode = "";
                            this.startPoint = "";
                            this.materSn = "";
                            this.matInfos = [];
                            this.sns = [];
                            // é‡ç½®ç„¦ç‚¹ï¼šå›žåˆ°æ‰˜ç›˜æ¡ç æ¡†ï¼Œå¼€å§‹æ–°çš„一轮扫描
                            this.resetFocusToBarcode();
                        } else {
                            this.$refs.uToast.show({
                                title: res.message,
                                type: "error"
                            });
                        }
                    })
                    .catch(err => {
                        this.$refs.uToast.show({
                            title: err.message || "请求失败",
                            type: "error"
                        });
                    })
                    .finally(() => {
                        this.isSubmitting = false;
                    });
            },
            // ==================== ç„¦ç‚¹é‡ç½®è¾…助方法 ====================
            resetFocusToBarcode() {
                this.barcodeFocus = true;
                this.startPointFocus = false;
                this.materSnFocus = false;
            },
            resetFocusToStartPoint() {
                this.barcodeFocus = false;
                this.startPointFocus = true;
                this.materSnFocus = false;
            },
            resetFocusToMaterSn() {
                this.barcodeFocus = false;
                this.startPointFocus = false;
                this.materSnFocus = true;
            }
        }
    }
</script>
<style lang="scss">
    @import '@/common/uni-ui.scss';
    page {
        background-color: #f5f7fa;
        font-size: 14px;
        color: #333;
    }
    .page-container {
        min-height: 100vh;
        display: flex;
        flex-direction: column;
    }
    .nav-header {
        background-color: #fff;
        padding: 12px 16px;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
        .segmented-control {
            --uni-segmented-control-border-color: #e5e7eb;
            --uni-segmented-control-bg-color: #f9fafb;
            --uni-segmented-control-active-color: #165dff;
            --uni-segmented-control-inactive-color: #666;
            --uni-segmented-control-height: 40px;
            border-radius: 8px;
        }
    }
    .main-content {
        flex: 1;
        padding: 16px;
    }
    .card-container {
        display: flex;
        flex-direction: column;
        gap: 16px;
    }
    .form-card {
        background-color: #fff;
        border-radius: 12px;
        padding: 20px;
        box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
    }
    .form-item {
        margin-bottom: 16px;
        &:last-of-type {
            margin-bottom: 24px;
        }
    }
    .input-field {
        --uni-easyinput-border-color: #e5e7eb;
        --uni-easyinput-bg-color: #f9fafb;
        --uni-easyinput-input-color: #333;
        --uni-easyinput-placeholder-color: #9ca3af;
        border-radius: 8px;
        padding: 10px 12px;
        height: 44px;
        transition: all 0.2s ease;
        &:focus {
            --uni-easyinput-border-color: #165dff;
            box-shadow: 0 0 0 2px rgba(22, 93, 255, 0.1);
        }
    }
    .selected-tip {
        display: flex;
        align-items: center;
        margin-top: 8px;
        padding: 6px 10px;
        background-color: #f0f7ff;
        border-radius: 6px;
        .tip-text {
            font-size: 12px;
            color: #6b7280;
            margin-right: 6px;
        }
        .sn-text {
            flex: 1;
            font-size: 12px;
            color: #165dff;
            font-weight: 500;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }
        .clear-icon {
            color: #94a3b8;
            margin-left: 6px;
            transition: color 0.2s ease;
            &:active {
                color: #ef4444;
            }
        }
    }
    .form-actions {
        display: flex;
        justify-content: center;
    }
    .btn-primary {
        --button-primary-background-color: #165dff;
        --button-primary-border-color: #165dff;
        --button-primary-text-color: #fff;
        --button-disabled-background-color: #94a3b8;
        --button-disabled-border-color: #94a3b8;
        border-radius: 8px;
        width: 100%;
        height: 48px;
        font-size: 16px;
        font-weight: 500;
        box-shadow: 0 4px 12px rgba(22, 93, 255, 0.2);
        transition: all 0.2s ease;
        &:not([disabled]):active {
            transform: translateY(1px);
            box-shadow: 0 2px 8px rgba(22, 93, 255, 0.2);
        }
    }
    .list-card {
        background-color: #fff;
        border-radius: 12px;
        box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
        overflow: hidden;
    }
    .list-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 16px 20px;
        border-bottom: 1px solid #f0f0f0;
        .list-title {
            font-size: 16px;
            font-weight: 600;
            color: #1f2937;
        }
        .count-badge {
            background-color: #e6f4ff;
            color: #165dff;
            padding: 2px 8px;
            border-radius: 100px;
            font-size: 12px;
            font-weight: 500;
        }
    }
    .material-list {
        --uni-list-item-border-color: #f9fafb;
    }
    .list-item {
        padding: 0;
        &:last-child {
            --uni-list-item-border-color: transparent;
        }
    }
    .list-item-content {
        position: relative;
        padding: 16px 20px;
    }
    .delete-icon {
        position: absolute;
        right: 20px;
        top: 50%;
        transform: translateY(-50%);
        color: #ef4444;
        transition: all 0.2s ease;
        &:active {
            transform: translateY(-50%) scale(0.95);
        }
    }
    .info-grid {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        gap: 8px 16px;
    }
    .info-row {
        display: flex;
        flex-direction: column;
        .label {
            font-size: 12px;
            color: #6b7280;
            margin-bottom: 2px;
        }
        .value {
            font-size: 14px;
            color: #1f2937;
            font-weight: 500;
        }
    }
    .empty-state {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        padding: 48px 20px;
        background-color: #fff;
        border-radius: 12px;
        box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
        .empty-text {
            margin-top: 16px;
            font-size: 14px;
            color: #9ca3af;
        }
    }
</style>
´úÂë¹ÜÀí/»´°²PDA/pages/stash/PPTaskTransport.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
<template>
</template>
<script>
</script>
<style>
</style>
´úÂë¹ÜÀí/»´°²PDA/pages/stash/ProEmptyBack.vue
@@ -11,7 +11,16 @@
                        @input="addressInput" />
                </uni-forms-item>
                <uni-forms-item>
                    <button @click="InEmpty" type="primary" size="default" style="margin-top: 2%;">空框回库</button>
                    <!-- ç©ºæ¡†å›žåº“按钮添加禁用状态和文字提示 -->
                    <button
                        @click="InEmpty"
                        type="primary"
                        size="default"
                        style="margin-top: 2%;"
                        :disabled="isSubmitting"
                    >
                        {{ isSubmitting ? '提交中...' : '空框回库' }}
                    </button>
                </uni-forms-item>
            </uni-forms>
        </view>
@@ -28,7 +37,9 @@
                focusStart:false,
                barcode: "",
                address: "",
                WarehouseId: ""
                WarehouseId: "",
                // æ–°å¢žï¼šé˜²é‡å¤ç‚¹å‡»çŠ¶æ€å˜é‡
                isSubmitting: false
            }
        },
        onShow() {},
@@ -36,10 +47,6 @@
            
        },
        methods: {
            // voiceSpeech(src) {
            //     innerAudioContext.src = src; // '../../static/success.mp3';
            //     innerAudioContext.play();
            // },
            barcodeInput() {
                this.$nextTick(function(x) {
                    if (this.barcode.length > 0) {
@@ -56,6 +63,7 @@
                })
            },
            InEmpty() {
                // 1. å‰ç½®æ ¡éªŒ
                if (this.barcode == "") {
                    this.$refs.uToast.show({
                        title: "请扫描托盘码",
@@ -70,6 +78,13 @@
                    })
                    return;
                }
                // 2. é˜²æ­¢é‡å¤ç‚¹å‡»ï¼šè¯·æ±‚中则直接返回
                if (this.isSubmitting) return;
                // 3. æ ‡è®°ä¸ºè¯·æ±‚中,禁用按钮
                this.isSubmitting = true;
                this.$u.post('/api/Task/EmptyBackTask?barcode=' + this.barcode + '&startPoint=' + this.address).then(
                    res => {
                        if (res.status) {
@@ -85,6 +100,15 @@
                                type: "error"
                            })
                        }
                    }).catch(err => {
                        // æ•获请求异常,提示错误
                        this.$refs.uToast.show({
                            title: err.message || "请求失败",
                            type: "error"
                        })
                    }).finally(() => {
                        // 4. è¯·æ±‚完成(成功/失败/异常)恢复按钮状态
                        this.isSubmitting = false;
                    })
            }
        }
´úÂë¹ÜÀí/»´°²PDA/pages/stash/boxing.vue
@@ -18,24 +18,20 @@
                            <uni-easyinput type="text" :placeholder="Testplaceholder" ref='midInput'
                                v-model="Initiallife" />
                        </uni-forms-item>
                        <!-- <uni-forms-item>
                            <checkbox checked="check">是否满盘</checkbox>
                        </uni-forms-item> -->
                        <uni-forms-item>
                            <button @click="submit" type="primary" size="default" style="margin-top: 2%;">组盘</button>
                            <!-- ç»„盘按钮添加禁用状态 -->
                            <button
                                @click="submit"
                                type="primary"
                                size="default"
                                style="margin-top: 2%;"
                                :disabled="isSubmitting"
                            >
                                {{ isSubmitting ? '组盘中...' : '组盘' }}
                            </button>
                        </uni-forms-item>
                    </uni-forms>
                    <uni-list>
                        <!-- <uni-list-item direction="column" v-for="item in matTotal" :key="item.matCode">
                            <template v-slot:body>
                                <view class="uni-list-box">
                                    <view class="uni-content">
                                        <view class="uni-title-sub uni-ellipsis-2">物料编码:{{item.matCode}}</view>
                                        <view class="uni-title-sub uni-ellipsis-2">数量:{{item.matQuantity}}</view>
                                    </view>
                                </view>
                            </template>
                        </uni-list-item> -->
                        <uni-list-item direction="column" v-for="(item,index) in matInfos" :key="index">
                            <template v-slot:body>
                                <view class="uni-list-box">
@@ -68,7 +64,16 @@
                                placeholder="请扫描地址条码" ref='midInput' :focus="addressFocus" />
                        </uni-forms-item>
                        <uni-forms-item>
                            <button @click="inbound" type="primary" size="default" style="margin-top: 2%;">入库确认</button>
                            <!-- å…¥åº“按钮添加禁用状态 -->
                            <button
                                @click="inbound"
                                type="primary"
                                size="default"
                                style="margin-top: 2%;"
                                :disabled="isInbounding"
                            >
                                {{ isInbounding ? '入库中...' : '入库确认' }}
                            </button>
                        </uni-forms-item>
                    </uni-forms>
                </view>
@@ -174,7 +179,11 @@
                addressdisabled: false,
                pksns: [],
                pkmaterSn: "",
                pkmatInfos: []
                pkmatInfos: [],
                // æ–°å¢žï¼šç»„盘请求状态(防止重复点击)
                isSubmitting: false,
                // æ–°å¢žï¼šå…¥åº“请求状态(防止重复点击)
                isInbounding: false
            }
        },
        onShow() {},
@@ -473,6 +482,7 @@
                })
            },
            inbound() {
                // 1. å‰ç½®æ ¡éªŒ
                if (this.inboundBarcode == "") {
                    this.$refs.uToast.show({
                        title: "请扫描托盘条码",
@@ -487,6 +497,13 @@
                    })
                    return;
                }
                // 2. é˜²æ­¢é‡å¤ç‚¹å‡»ï¼šå¦‚果正在请求,直接返回
                if (this.isInbounding) return;
                // 3. æ ‡è®°ä¸ºè¯·æ±‚中,禁用按钮
                this.isInbounding = true;
                var postData = {
                    MainData: {
                        "barcode": this.inboundBarcode,
@@ -519,6 +536,9 @@
                        title: err.message,
                        type: "error"
                    })
                }).finally(() => {
                    // 4. è¯·æ±‚完成(成功/失败)后,恢复按钮状态
                    this.isInbounding = false;
                })
            },
            inputChangebarcode() {
@@ -562,6 +582,7 @@
                this.sns.splice(res, 1);
            },
            submit() {
                // 1. å‰ç½®æ ¡éªŒ
                if (this.barcode == "") {
                    this.$refs.uToast.show({
                        title: "请扫描托盘条码",
@@ -593,6 +614,13 @@
                        return;
                    }
                }
                // 2. é˜²æ­¢é‡å¤ç‚¹å‡»ï¼šå¦‚果正在请求,直接返回
                if (this.isSubmitting) return;
                // 3. æ ‡è®°ä¸ºè¯·æ±‚中,禁用按钮
                this.isSubmitting = true;
                if (this.warehouseId == 2) { //油墨仓库区ID
                    this.sn = this.sns[0];
                    for (var i = 0; i < this.Initiallife - 1; i++) {
@@ -620,6 +648,9 @@
                            type: "error"
                        })
                    }
                }).finally(() => {
                    // 4. è¯·æ±‚完成(成功/失败)后,恢复按钮状态
                    this.isSubmitting = false;
                })
            }
        }
´úÂë¹ÜÀí/»´°²PDA/pages/stash/raworderboxing.vue
@@ -22,28 +22,19 @@
                                v-model="Initiallife" />
                        </uni-forms-item>
                        <!-- <uni-forms-item>
                            <checkbox checked="check">是否满盘</checkbox>
                        </uni-forms-item> -->
                        <uni-forms-item>
                            <view style="display: flex;justify-content: space-around;margin-top: 2%;">
                                <button @click="reset" type="default" size="default"
                                    style="width: 160rpx;border: 1rpx solid #007aff;color: #007aff;">重置</button>
                                <button @click="submit" type="primary" size="default" style="width: 160rpx;">组盘</button>
                                <!-- ç»„盘按钮添加禁用状态和文字提示 -->
                                <button @click="submit" type="primary" size="default" style="width: 160rpx;"
                                    :disabled="isSubmitting">
                                    {{ isSubmitting ? '组盘中...' : '组盘' }}
                                </button>
                            </view>
                        </uni-forms-item>
                    </uni-forms>
                    <uni-list>
                        <!-- <uni-list-item direction="column" v-for="item in matTotal" :key="item.matCode">
                            <template v-slot:body>
                                <view class="uni-list-box">
                                    <view class="uni-content">
                                        <view class="uni-title-sub uni-ellipsis-2">物料编码:{{item.matCode}}</view>
                                        <view class="uni-title-sub uni-ellipsis-2">数量:{{item.matQuantity}}</view>
                                    </view>
                                </view>
                            </template>
                        </uni-list-item> -->
                        <uni-list-item direction="column" v-for="(item,index) in matInfos" :key="index">
                            <template v-slot:body>
                                <view class="uni-list-box">
@@ -76,7 +67,11 @@
                                placeholder="请扫描地址条码" ref='midInput' :focus="addressFocus" />
                        </uni-forms-item>
                        <uni-forms-item>
                            <button @click="inbound" type="primary" size="default" style="margin-top: 2%;">入库确认</button>
                            <!-- å…¥åº“确认按钮添加禁用状态和文字提示 -->
                            <button @click="inbound" type="primary" size="default" style="margin-top: 2%;"
                                :disabled="isInbounding">
                                {{ isInbounding ? '入库中...' : '入库确认' }}
                            </button>
                        </uni-forms-item>
                    </uni-forms>
                </view>
@@ -92,7 +87,6 @@
                                        <view style="font-size: 18px;">物料编码:{{item.materielCode}}</view>
                                        <view>物料名称:{{item.materielName}}</view>
                                        <view>物料规格:{{item.materielSpec}}</view>
                                        <!-- <view style="font-size: 18px;">物料名称:{{item.matName}}</view> -->
                                        <view style="font-size: 18px;">数量:{{item.orderQuantity+item.unit}}</view>
                                        <view style="font-size: 18px;">组盘数量:{{item.receiptQuantity}}</view>
                                    </view>
@@ -114,8 +108,11 @@
                            <view style="display: flex;justify-content: space-around;margin-top: 2%;">
                                <button @click="resetInPk" type="default" size="default"
                                    style="width: 160rpx;border: 1rpx solid #007aff;color: #007aff;">重置</button>
                                <!-- å…¥å¹³åº“按钮添加禁用状态和文字提示 -->
                                <button @click="pksubmit" type="primary" size="default"
                                    style="margin-top: 2%;">入平库</button>
                                    style="margin-top: 2%;" :disabled="isPkSubmitting">
                                    {{ isPkSubmitting ? '入库中...' : '入平库' }}
                                </button>
                            </view>
                        </uni-forms-item>
@@ -180,7 +177,11 @@
                Testcheck: false,
                pkmaterSn: "",
                pkmatInfos: [],
                addressdisabled: false
                addressdisabled: false,
                // æ–°å¢žï¼šé˜²é‡å¤ç‚¹å‡»çŠ¶æ€å˜é‡
                isSubmitting: false,    // ç»„盘请求状态
                isInbounding: false,   // å…¥åº“确认请求状态
                isPkSubmitting: false  // å…¥å¹³åº“请求状态
            }
        },
        onShow() {},
@@ -210,10 +211,6 @@
            this.getData();
        },
        methods: {
            // voiceSpeech(src) {
            //     innerAudioContext.src = src; // '../../static/success.mp3';
            //     innerAudioContext.play();
            // },
            updateFocus() {
                debugger
                this.$nextTick(() => {
@@ -258,14 +255,7 @@
            barcodeInput() {
                this.$nextTick(function(x) {
                    if (this.barcode.length > 0) {
                        // if (this.barcode.substring(0, 1) == 'A' || this.barcode.substring(0, 2) == 'TP') {
                        this.focus = true;
                        // } else {
                        //     this.$refs.uToast.show({
                        //         title: "扫码错误,请扫描托盘码",
                        //         type: "error"
                        //     })
                        // }
                    }
                })
            },
@@ -283,29 +273,19 @@
                                this.Testcheck = false;
                                if (res.status) {
                                    this.sns.push(res.data.serialNumber);
                                    this.matInfos.push(res.data);
                                    if (res.message) {
                                        this.$refs.uToast.show({
                                            title: res.message,
                                            type: "error"
                                        })
                                        // setTimeout(() => {
                                        //     this.voiceSpeech('../../static/fail.mp3');
                                        // }, 100);
                                        return;
                                    }
                                    // setTimeout(() => {
                                    //     this.voiceSpeech('../../static/success.mp3');
                                    // }, 100);
                                } else {
                                    this.$refs.uToast.show({
                                        title: res.message,
                                        type: "error"
                                    })
                                    // setTimeout(() => {
                                    //     this.voiceSpeech('../../static/fail.mp3');
                                    // }, 100);
                                }
                            })
                        }
@@ -318,9 +298,7 @@
            pksnInput() {
                this.$nextTick(() => {
                    if (this.pkmaterSn != "") {
                        var matSn = this.pkmaterSn;
                        if(matSn.indexOf("POHA")>0){
                            this.$u.post('/api/MaterielInfo/CodeAnalysis?serNum=' + matSn, {}).then((res) => {
                                if (res.status) {
@@ -331,23 +309,14 @@
                                            title: res.message,
                                            type: "error"
                                        })
                                        // setTimeout(() => {
                                        //     this.voiceSpeech('../../static/fail.mp3');
                                        // }, 100);
                                        return;
                                    }
                                    // setTimeout(() => {
                                    //     this.voiceSpeech('../../static/success.mp3');
                                    // }, 100);
                                    return;
                                } else {
                                    this.$refs.uToast.show({
                                        title: res.message,
                                        type: "error"
                                    })
                                    // setTimeout(() => {
                                    //     this.voiceSpeech('../../static/fail.mp3');
                                    // }, 100);
                                }
                            })
                        }
@@ -358,6 +327,7 @@
                })
            },
            inbound() {
                // 1. å‰ç½®æ ¡éªŒ
                if (this.inboundBarcode == "") {
                    this.$refs.uToast.show({
                        title: "请扫描托盘条码",
@@ -372,6 +342,13 @@
                    })
                    return;
                }
                // 2. é˜²æ­¢é‡å¤ç‚¹å‡»ï¼šè¯·æ±‚中则直接返回
                if (this.isInbounding) return;
                // 3. æ ‡è®°ä¸ºè¯·æ±‚中,禁用按钮
                this.isInbounding = true;
                var postData = {
                    MainData: {
                        "barcode": this.inboundBarcode,
@@ -401,6 +378,9 @@
                        title: err.message,
                        type: "error"
                    })
                }).finally(() => {
                    // 4. è¯·æ±‚完成(成功/失败)恢复按钮状态
                    this.isInbounding = false;
                })
            },
            inputChangebarcode() {
@@ -435,6 +415,7 @@
                this.pksns = [];
            },
            pksubmit() {
                // 1. å‰ç½®æ ¡éªŒ
                if (this.pkmatInfos.length == 0) {
                    this.$refs.uToast.show({
                        title: "请扫描内箱标签",
@@ -442,6 +423,13 @@
                    })
                    return;
                }
                // 2. é˜²æ­¢é‡å¤ç‚¹å‡»ï¼šè¯·æ±‚中则直接返回
                if (this.isPkSubmitting) return;
                // 3. æ ‡è®°ä¸ºè¯·æ±‚中,禁用按钮
                this.isPkSubmitting = true;
                this.$u.post('/api/InboundOrder/InPinKu?warehouseId=' + this.warehouseId + "&orderNo=" + this.orderNo, this
                    .pksns).then(res => {
                    if (res.status) {
@@ -458,9 +446,18 @@
                            type: "error"
                        })
                    }
                }).catch(err => {
                    this.$refs.uToast.show({
                        title: err.message,
                        type: "error"
                    })
                }).finally(() => {
                    // 4. è¯·æ±‚完成(成功/失败)恢复按钮状态
                    this.isPkSubmitting = false;
                })
            },
            submit() {
                // 1. å‰ç½®æ ¡éªŒ
                if (this.barcode == "") {
                    this.$refs.uToast.show({
                        title: "请扫描托盘条码",
@@ -492,6 +489,13 @@
                        return;
                    }
                }
                // 2. é˜²æ­¢é‡å¤ç‚¹å‡»ï¼šè¯·æ±‚中则直接返回
                if (this.isSubmitting) return;
                // 3. æ ‡è®°ä¸ºè¯·æ±‚中,禁用按钮
                this.isSubmitting = true;
                if (this.warehouseId == 2) { //油墨仓库区ID
                    this.sn = this.sns[0];
                    for (var i = 0; i < this.Initiallife - 1; i++) {
@@ -503,7 +507,6 @@
                        "palletCode": this.barcode,
                        "orderNo": this.orderNo,
                        "initiallife": this.Initiallife,
                        // "isFull": this.check
                        "warehouseId": this.warehouseId
                    },
                    DelKeys: this.sns
@@ -528,6 +531,14 @@
                            type: "error"
                        })
                    }
                }).catch(err => {
                    this.$refs.uToast.show({
                        title: err.message,
                        type: "error"
                    })
                }).finally(() => {
                    // 4. è¯·æ±‚完成(成功/失败)恢复按钮状态
                    this.isSubmitting = false;
                })
            }
        }