xiazhengtongxue
18 小时以前 0aed9c9ee65bd8a17837d83ec05e756d11fab297
Merge branch 'dev' of http://115.159.85.185:8098/r/SuZhouGuanHong/ShanMeiXinNengYuan into dev
已添加1个文件
已修改32个文件
486 ■■■■ 文件已修改
Code/.omc/state/subagent-tracking.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Core/Filter/ApiAuthorizeFilter.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Core/LogHelper/QuartzLogger.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Core/Middlewares/HttpRequestMiddleware.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Program.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server.csproj 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/CommonConveyorLineNewJob.cs 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTaskFilter.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/QuartzLogHelper.cs 39 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/CommonStackerCraneJob.cs 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneCommandBuilder.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/api/http.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/extension/stock/extend/RobotSelect.vue 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/extension/stock/stockInfo.jsx 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/extension/system/Mes_Log.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/views/system/Mes_Log.vue 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/MesService.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/Filter/ApiAuthorizeFilter.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/Middlewares/HttpRequestMiddleware.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_DTO/MES/BindContainerRequestDto.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_DTO/MES/UnbindContainerRequestDto.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_IBasicService/IMesService.cs 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_IBasicService/IMesUploadHelper.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/MesUploadHelper.cs 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WCS/TaskService_Inbound.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WCS/TaskService_Outbound.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockInfoController.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockInfoDetailController.cs 89 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/.omc/state/subagent-tracking.json
@@ -1459,5 +1459,5 @@
  "total_spawned": 135,
  "total_completed": 157,
  "total_failed": 0,
  "last_updated": "2026-04-20T17:02:18.739Z"
  "last_updated": "2026-04-21T06:46:41.255Z"
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Core/Filter/ApiAuthorizeFilter.cs
@@ -7,6 +7,7 @@
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Hosting;
using WIDESEAWCS_Core.Authorization;
@@ -112,7 +113,7 @@
                int ExpMinutes = AppSettings.Get("ExpMinutes").ObjToInt();
                if ((expDate.GetValueOrDefault() - DateTime.Now).TotalMinutes < ExpMinutes / 3 && context.HttpContext.Request.Path != replaceTokenPath)
                {
                    context.HttpContext.Response.Headers.Add("wideseawcs_exp", "1");
                    context.HttpContext.Response.Headers.Append("wideseawcs_exp", "1");
                }
            }
        }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Core/LogHelper/QuartzLogger.cs
@@ -166,7 +166,7 @@
                    string fileName = GetLogFileName(entry.Source);
                    string filePath = Path.Combine(_logFolder, fileName);
                    string content = entry.ToFormattedString() + Environment.NewLine;
                    ConsoleHelper.WriteInfoLine(content);
                    //ConsoleHelper.WriteInfoLine(content);
                    File.AppendAllText(filePath, content);
                }
            }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Core/Middlewares/HttpRequestMiddleware.cs
@@ -25,7 +25,7 @@
        public async Task InvokeAsync(HttpContext context)
        {
            
            context.Response.Headers.Add("Access-Control-Expose-Headers", "wideseawcs_exp");
            context.Response.Headers.Append("Access-Control-Expose-Headers", "wideseawcs_exp");
            await _next(context);
        }
    }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Program.cs
@@ -49,7 +49,7 @@
        .Enrich.WithProperty("Application", "WCS")
        // è®¾ç½®Microsoft命名空间的日志级别为Information
        // è¿™æ ·å¯ä»¥å‡å°‘Microsoft框架本身的详细日志,避免过多的Debug日志
        .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
        .MinimumLevel.Override("Microsoft", LogEventLevel.Debug)
        .WriteTo.Console()  // æ·»åŠ æŽ§åˆ¶å°è¾“å‡ºæŽ¥æ”¶å™¨ï¼Œæ—¥å¿—å°†æ˜¾ç¤ºåœ¨æŽ§åˆ¶å°çª—å£ä¸­
                            // æ·»åŠ æ–‡ä»¶è¾“å‡ºæŽ¥æ”¶å™¨ï¼Œå°†æ—¥å¿—å†™å…¥æ–‡ä»¶ç³»ç»Ÿ
        .WriteTo.File(
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server.csproj
@@ -65,7 +65,7 @@
    </ItemGroup>
    <ItemGroup>
        <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
        <PackageReference Include="Swashbuckle.AspNetCore" Version="8.0.0" />
    </ItemGroup>
    <ItemGroup>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
@@ -39,7 +39,7 @@
  //跨域
  "Cors": {
    "PolicyName": "CorsIpAccess", //策略名称
    "EnableAllIPs": false, //当为true时,开放所有IP均可访问。
    "EnableAllIPs": true, //当为true时,开放所有IP均可访问。
    // æ”¯æŒå¤šä¸ªåŸŸåç«¯å£ï¼Œæ³¨æ„ç«¯å£å·åŽä¸è¦å¸¦/斜杆:比如localhost:8000/,是错的
    // æ³¨æ„ï¼Œhttp://127.0.0.1:1818 å’Œ http://localhost:1818 æ˜¯ä¸ä¸€æ ·çš„
    "IPs": "http://127.0.0.1:8080,http://localhost:8080,http://localhost:8081"
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/CommonConveyorLineNewJob.cs
@@ -1,15 +1,14 @@
using MapsterMapper;
using Masuit.Tools;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Quartz;
using Serilog;
using SqlSugar;
using WIDESEA_Core;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
@@ -41,7 +40,6 @@
        /// ä»»åŠ¡æœåŠ¡
        /// </summary>
        private readonly ITaskService _taskService;
        /// <summary>
        /// æœºå™¨äººä»»åŠ¡æœåŠ¡
@@ -82,7 +80,7 @@
        /// <summary>
        /// æ—¥å¿—记录器
        /// </summary>
        private readonly ILogger<CommonConveyorLineNewJob> _logger;
        private readonly ILogger _logger;
        /// <summary>
        /// ç›®æ ‡åœ°å€åˆ°è®¾å¤‡ç±»åž‹çš„æ˜ å°„
@@ -90,6 +88,11 @@
        /// <remarks>
        /// </remarks>
        private static List<string> AddressToDeviceType = new List<string> { "11020", "11028" };
        /// <summary>
        /// æ‰˜ç›˜æ£€æŸ¥ä½ç½®çš„æœ€è¿‘执行时间(用于30秒间隔限制)
        /// </summary>
        private static readonly Dictionary<string, DateTime> _lastPalletCheckTime = new();
        /// <summary>
        /// æž„造函数
@@ -100,7 +103,7 @@
        /// <param name="mapper">对象映射器</param>
        /// <param name="httpClientHelper">HTTP å®¢æˆ·ç«¯å¸®åŠ©ç±»</param>
        /// <param name="logger">日志记录器</param>
        public CommonConveyorLineNewJob(ITaskService taskService, ITaskExecuteDetailService taskExecuteDetailService, IRouterService routerService, IMapper mapper, HttpClientHelper httpClientHelper, ILogger<CommonConveyorLineNewJob> logger, IRobotTaskService robotTaskService)
        public CommonConveyorLineNewJob(ITaskService taskService, ITaskExecuteDetailService taskExecuteDetailService, IRouterService routerService, IMapper mapper, HttpClientHelper httpClientHelper, ILogger logger, IRobotTaskService robotTaskService)
        {
            _taskService = taskService;
            _taskExecuteDetailService = taskExecuteDetailService;
@@ -179,6 +182,13 @@
                            // å¦‚果当前设备在检查列表中
                            if (checkPalletPositions.Any(x => x.Code == childDeviceCode))
                            {
                                // 30秒间隔限制
                                if (_lastPalletCheckTime.TryGetValue(childDeviceCode, out var lastTime) &&
                                    (DateTime.Now - lastTime).TotalSeconds < 30)
                                {
                                    continue;
                                }
                                // æ£€æŸ¥è¾“送线状态(是否有托盘)
                                if (command.CV_State == 2)
                                {
@@ -196,6 +206,8 @@
                                            TargetAddress = childDeviceCode
                                        }.Serialize());
                                        _lastPalletCheckTime[childDeviceCode] = DateTime.Now;
                                        // å¦‚果请求成功,接收 WMS è¿”回的任务
                                        if (responseResult.IsSuccess && responseResult.Data.Status)
                                        {
@@ -208,7 +220,7 @@
                                }
                            }
                            #endregion
                            #endregion æ£€æµ‹æ˜¯å¦éœ€è¦ç©ºæ‰˜ç›˜
                            // ========== æ£€æŸ¥ PLC_STB æ ‡å¿— ==========
                            // åªæœ‰å½“ PLC_STB ä¸º 1 æ—¶æ‰å¤„理任务
@@ -278,7 +290,6 @@
                                        RobotTargetAddressLineCode = childDeviceCode,
                                        RobotTaskNum = num, // ç”Ÿæˆä»»åŠ¡å·
                                        RobotDispatchertime = DateTime.Now,
                                    };
                                    if (_robotTaskService.AddData(robotTask).Status)
                                    {
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs
@@ -1,9 +1,7 @@
using MapsterMapper;
using Microsoft.Extensions.Logging;
using Serilog;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
@@ -201,7 +199,6 @@
            Dt_Task? task = _taskFilter.QueryExecutingTask(command.TaskNo, childDeviceCode);
            if (task != null)
            {
                // æ›´æ–°ä»»åŠ¡çŠ¶æ€åˆ°ä¸‹ä¸€é˜¶æ®µï¼ˆé€šå¸¸æ˜¯å®Œæˆï¼‰
                if (_taskService.UpdateTaskStatusToNext(task).Status)
                {
@@ -209,8 +206,6 @@
                    conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
                    QuartzLogHelper.LogInfo(_logger, "ConveyorLineInFinish:入库完成,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"入库完成,任务号: {task.TaskNum}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode);
                }
            }
        }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs
@@ -1,5 +1,4 @@
using Microsoft.Extensions.Logging;
using WIDESEAWCS_Core.LogHelper;
using Serilog;
using WIDESEAWCS_QuartzJob;
namespace WIDESEAWCS_Tasks
@@ -276,7 +275,7 @@
            if (device == null)
            {
                // è®¾å¤‡æœªæ‰¾åˆ°æ—¶è®°å½•调试日志,方便排查配置问题
                _logger.LogDebug("FindDevice:未找到 {DeviceName}", deviceName);
                _logger.Debug("FindDevice:未找到 {DeviceName}", deviceName);
            }
            return device; // å¯èƒ½ä¸º null,由调用方负责 null æ£€æŸ¥
        }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTaskFilter.cs
@@ -1,5 +1,4 @@
using Microsoft.Extensions.Logging;
using WIDESEAWCS_Core.LogHelper;
using Serilog;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/QuartzLogHelper.cs
@@ -1,4 +1,4 @@
using Microsoft.Extensions.Logging;
using Serilog;
using WIDESEAWCS_Core.LogHelper;
namespace WIDESEAWCS_Tasks;
@@ -23,7 +23,7 @@
    /// <param name="args">ILogger ç»“构化日志的参数</param>
    public static void LogError(ILogger logger, Exception ex, string loggerMessage, string quartzMessage, string deviceCode, params object[] args)
    {
        logger.LogError(ex, loggerMessage, args);
        logger.Error(ex, loggerMessage, args);
        QuartzLogger.Error(quartzMessage, deviceCode, ex);
    }
@@ -37,7 +37,7 @@
    /// <param name="args">ILogger ç»“构化日志的参数</param>
    public static void LogError(ILogger logger, string loggerMessage, string quartzMessage, string deviceCode, params object[] args)
    {
        logger.LogError(loggerMessage, args);
        logger.Error(loggerMessage, args);
        QuartzLogger.Error(quartzMessage, deviceCode);
    }
@@ -51,8 +51,21 @@
    /// <param name="args">ILogger ç»“构化日志的参数</param>
    public static void LogInfo(ILogger logger, string loggerMessage, string quartzMessage, string deviceCode, params object[] args)
    {
        logger.LogInformation(loggerMessage, args);
        logger.Information(loggerMessage, args);
        QuartzLogger.Info(quartzMessage, deviceCode);
    }
    /// <summary>
    /// è®°å½•信息日志
    /// </summary>
    /// <param name="logger">ILogger å®žä¾‹</param>
    /// <param name="loggerMessage">ILogger çš„结构化日志模板</param>
    /// <param name="quartzMessage">QuartzLogger çš„æ—¥å¿—消息</param>
    /// <param name="deviceCode">设备编码</param>
    public static void LogInfo(ILogger logger, string loggerMessage, string deviceCode)
    {
        logger.Information(loggerMessage);
        QuartzLogger.Info(loggerMessage, deviceCode);
    }
    /// <summary>
@@ -65,7 +78,7 @@
    /// <param name="args">ILogger ç»“构化日志的参数</param>
    public static void LogWarn(ILogger logger, string loggerMessage, string quartzMessage, string deviceCode, params object[] args)
    {
        logger.LogWarning(loggerMessage, args);
        logger.Warning(loggerMessage, args);
        QuartzLogger.Warn(quartzMessage, deviceCode);
    }
@@ -79,7 +92,21 @@
    /// <param name="args">ILogger ç»“构化日志的参数</param>
    public static void LogDebug(ILogger logger, string loggerMessage, string quartzMessage, string deviceCode, params object[] args)
    {
        logger.LogDebug(loggerMessage, args);
        logger.Debug(loggerMessage, args);
        QuartzLogger.Debug(quartzMessage, deviceCode);
    }
    /// <summary>
    /// è®°å½•调试日志
    /// </summary>
    /// <param name="logger">ILogger å®žä¾‹</param>
    /// <param name="loggerMessage">ILogger çš„结构化日志模板(支持占位符)</param>
    /// <param name="quartzMessage">QuartzLogger çš„æ—¥å¿—消息</param>
    /// <param name="deviceCode">设备编码</param>
    /// <param name="args">ILogger ç»“构化日志的参数</param>
    public static void LogDebug(ILogger logger, string loggerMessage, string deviceCode)
    {
        logger.Debug(loggerMessage);
        QuartzLogger.Debug(loggerMessage, deviceCode);
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/CommonStackerCraneJob.cs
@@ -1,7 +1,8 @@
using Microsoft.Extensions.Logging;
//using Microsoft.Extensions.Logging;
using Quartz;
using Serilog;
using WIDESEA_Core;
using WIDESEAWCS_Core;
using WIDESEAWCS_Common.Constants;
using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_ITaskInfoRepository;
using WIDESEAWCS_ITaskInfoService;
@@ -10,7 +11,6 @@
using WIDESEAWCS_QuartzJob.Service;
using WIDESEAWCS_QuartzJob.StackerCrane;
using WIDESEAWCS_QuartzJob.StackerCrane.Enum;
using WIDESEAWCS_Common.Constants;
using WIDESEAWCS_Tasks.StackerCraneJob;
namespace WIDESEAWCS_Tasks
@@ -81,7 +81,7 @@
        /// <summary>
        /// æ—¥å¿—记录器
        /// </summary>
        private readonly ILogger<CommonStackerCraneJob> _logger;
        private readonly ILogger  _logger;
        /// <summary>
        /// å †åž›æœºè®¾å¤‡ç¼–码
@@ -103,7 +103,7 @@
            ITaskRepository taskRepository,
            IRouterService routerService,
            HttpClientHelper httpClientHelper,
            ILogger<CommonStackerCraneJob> logger)
            ILogger logger)
        {
            _taskService = taskService;
            _taskExecuteDetailService = taskExecuteDetailService;
@@ -169,10 +169,12 @@
        {
            try
            {
                //QuartzLogger.Info($"CommonStackerCraneJob Execute:开始执行堆垛机任务调度 ã€{DateTime.Now.ToString("F")}】", "CommonStackerCraneJob Execute ");
                // ä»Ž JobDataMap èŽ·å–å †åž›æœºè®¾å¤‡å‚æ•°
                bool flag = context.JobDetail.JobDataMap.TryGetValue("JobParams", out object? value);
                if (!flag || value is not CommonStackerCrane commonStackerCrane)
                {
                    _logger.Information("Execute:参数无效,未找到 JobParams æˆ–类型不匹配");
                    // å‚数无效,直接返回
                    QuartzLogHelper.LogWarn(_logger, "Execute:参数无效", "Execute:参数无效", "CommonStackerCraneJob");
                    return Task.CompletedTask;
@@ -208,6 +210,8 @@
                    return Task.CompletedTask;
                }
                // ========== æž„建命令 ==========
                // å‘½ä»¤æž„建下沉到专用构建器
                object? stackerCraneTaskCommand = _commandBuilder.ConvertToStackerCraneTaskCommand(task);
@@ -240,6 +244,10 @@
                // è®°å½•异常
                QuartzLogHelper.LogError(_logger, ex, "Execute:执行异常,设备: {DeviceCode}", $"执行异常: {ex.Message}", _deviceCode, _deviceCode);
            }
            finally
            {
                QuartzLogHelper.LogInfo(_logger, $"CommonStackerCraneJob Execute:堆垛机任务调度执行完成 ã€{DateTime.Now.ToString("F")}】", _deviceCode);
            }
            return Task.CompletedTask;
        }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneCommandBuilder.cs
@@ -1,9 +1,7 @@
using Microsoft.Extensions.Logging;
using System;
using Serilog;
using System.Diagnostics.CodeAnalysis;
using WIDESEAWCS_Common.Constants;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob.Models;
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs
@@ -1,12 +1,11 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Serilog;
using System.Diagnostics.CodeAnalysis;
using WIDESEA_Core;
using WIDESEAWCS_Common.Constants;
using WIDESEAWCS_Common.HttpEnum;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
@@ -101,15 +100,14 @@
            Dt_Task? candidateTask;
            var deviceCode = commonStackerCrane.DeviceCode;
            //_logger.LogInformation("SelectTask:开始选择任务,设备: {DeviceCode},上一任务类型: {LastTaskType}", deviceCode, commonStackerCrane.LastTaskType);
            //QuartzLogger.Info($"开始选择任务,设备: {deviceCode},上一任务类型: {commonStackerCrane.LastTaskType}", deviceCode);
            QuartzLogHelper.LogDebug(_logger, $"开始选择任务,设备: {deviceCode},上一任务类型: {commonStackerCrane.LastTaskType}",commonStackerCrane.DeviceName);
            // æ ¹æ®ä¸Šä¸€ä»»åŠ¡ç±»åž‹å†³å®šæŸ¥è¯¢ç­–ç•¥
            if (commonStackerCrane.LastTaskType == null || commonStackerCrane.LastTaskType == TaskRelocationTypeEnum.Relocation.GetHashCode())
            {
                // æ²¡æœ‰ä¸Šä¸€ä»»åŠ¡ç±»åž‹ï¼ŒæŸ¥è¯¢æ™®é€šä»»åŠ¡
                candidateTask = _taskService.QueryStackerCraneTask(deviceCode);
                //QuartzLogHelper.LogDebug(_logger, "SelectTask:查询普通任务,设备: {DeviceCode},结果: {TaskNum}", $"查询普通任务,设备: {deviceCode},结果: {candidateTask?.TaskNum}", deviceCode, deviceCode, candidateTask?.TaskNum);
                QuartzLogHelper.LogDebug(_logger, $"查询普通任务,设备: {deviceCode},结果: {candidateTask?.TaskNum}", commonStackerCrane.DeviceName);
            }
            else if (commonStackerCrane.LastTaskType.GetValueOrDefault().GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup)
            {
@@ -117,26 +115,26 @@
                candidateTask = _taskService.QueryStackerCraneInTask(deviceCode);
                // å¦‚果没有入库任务,再查一下出库任务
                candidateTask ??= _taskService.QueryStackerCraneOutTask(deviceCode);
                //QuartzLogHelper.LogDebug(_logger, "SelectTask:出库后优先查入库,设备: {DeviceCode},结果: {TaskNum}", $"出库后优先查入库,设备: {deviceCode},结果: {candidateTask?.TaskNum}", deviceCode, deviceCode, candidateTask?.TaskNum);
                QuartzLogHelper.LogDebug(_logger, $"出库后优先查入库,设备: {deviceCode},结果: {candidateTask?.TaskNum}", commonStackerCrane.DeviceName);
            }
            else
            {
                // ä¸Šä¸€ä»»åŠ¡æ˜¯å…¥åº“ï¼ˆéžå‡ºåº“ï¼‰ï¼Œä¼˜å…ˆæŸ¥å‡ºåº“ä»»åŠ¡
                candidateTask = _taskService.QueryStackerCraneOutTask(deviceCode);
                //QuartzLogHelper.LogDebug(_logger, "SelectTask:入库后优先查出库,设备: {DeviceCode},结果: {TaskNum}", $"入库后优先查出库,设备: {deviceCode},结果: {candidateTask?.TaskNum}", deviceCode, deviceCode, candidateTask?.TaskNum);
                QuartzLogHelper.LogDebug(_logger, $"入库后优先查出库,设备: {deviceCode},结果: {candidateTask?.TaskNum}", commonStackerCrane.DeviceName);
            }
            // å¦‚果没有候选任务,返回 null
            if (candidateTask == null)
            {
                //QuartzLogHelper.LogDebug(_logger, "SelectTask:没有候选任务,设备: {DeviceCode}", $"没有候选任务,设备: {deviceCode}", deviceCode, deviceCode);
                QuartzLogHelper.LogDebug(_logger, $"没有候选任务,设备: {deviceCode}", commonStackerCrane.DeviceName);
                return null;
            }
            // å¦‚果不是出库任务,直接返回
            if (candidateTask.TaskType.GetTaskTypeGroup() != TaskTypeGroup.OutbondGroup)
            {
                QuartzLogHelper.LogInfo(_logger, "SelectTask:选中非出库任务,设备: {DeviceCode},任务号: {TaskNum},任务类型: {TaskType}", $"选中非出库任务,任务号: {candidateTask.TaskNum},任务类型: {candidateTask.TaskType}", deviceCode, deviceCode, candidateTask.TaskNum, candidateTask.TaskType);
                QuartzLogHelper.LogDebug(_logger, $"选中非出库任务,任务号: {candidateTask.TaskNum},任务类型: {candidateTask.TaskType}", commonStackerCrane.DeviceName);
                return candidateTask;
            }
@@ -144,7 +142,7 @@
            Dt_Task? selectedTask = TrySelectOutboundTask(candidateTask);
            if (selectedTask != null)
            {
                QuartzLogHelper.LogInfo(_logger, "SelectTask:选中出库任务,设备: {DeviceCode},任务号: {TaskNum}", $"选中出库任务,任务号: {selectedTask.TaskNum}", deviceCode, deviceCode, selectedTask.TaskNum);
                QuartzLogHelper.LogDebug(_logger, $"选中出库任务,任务号: {selectedTask.TaskNum}", commonStackerCrane.DeviceName);
                return selectedTask;
            }
@@ -161,14 +159,14 @@
                selectedTask = TrySelectOutboundTask(alternativeTask);
                if (selectedTask != null)
                {
                    QuartzLogHelper.LogInfo(_logger, "SelectTask:选中备选出库任务,设备: {DeviceCode},任务号: {TaskNum}", $"选中备选出库任务,任务号: {selectedTask.TaskNum}", deviceCode, deviceCode, selectedTask.TaskNum);
                    QuartzLogHelper.LogDebug(_logger, $"选中备选出库任务,任务号: {selectedTask.TaskNum}", commonStackerCrane.DeviceName);
                    return selectedTask;
                }
            }
            // æ²¡æœ‰å¯ç”¨å‡ºåº“任务,尝试返回入库任务
            var inboundTask = _taskService.QueryStackerCraneInTask(deviceCode);
            QuartzLogHelper.LogInfo(_logger, "SelectTask:返回入库任务,设备: {DeviceCode},任务号: {TaskNum}", $"返回入库任务,任务号: {inboundTask?.TaskNum}", deviceCode, deviceCode, inboundTask?.TaskNum);
            QuartzLogHelper.LogDebug(_logger, $"返回入库任务,任务号: {inboundTask?.TaskNum}", commonStackerCrane.DeviceName);
            return inboundTask;
        }
Code/WMS/WIDESEA_WMSClient/src/api/http.js
@@ -12,7 +12,7 @@
let loadingInstance;
let loadingStatus = false;
if (process.env.NODE_ENV == 'development') {
    axios.defaults.baseURL = 'http://127.0.0.1:9291/';
    axios.defaults.baseURL = window.webConfig.webApiProduction;
}
else if (process.env.NODE_ENV == 'debug') {
    axios.defaults.baseURL = window.webConfig.webApiBaseUrl;
Code/WMS/WIDESEA_WMSClient/src/extension/stock/extend/RobotSelect.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,125 @@
<template>
  <div>
    <vol-box
      v-model="showDetialBox"
      :lazy="true"
      width="400px"
      :padding="15"
      title="选择机械手"
    >
      <div>
        <el-form>
          <el-form-item required label="机械手:">
            <el-select v-model="selectedRobot" placeholder="请选择机械手" style="width: 100%">
              <el-option
                v-for="item in robotList"
                :key="item.robotCode"
                :label="item.robotName"
                :value="item.robotCode"
              >
              </el-option>
            </el-select>
          </el-form-item>
        </el-form>
      </div>
      <template #footer>
        <el-button type="primary" size="small" @click="submit">确认</el-button>
        <el-button type="danger" size="small" @click="close">关闭</el-button>
      </template>
    </vol-box>
  </div>
</template>
<script>
import VolBox from "@/components/basic/VolBox.vue";
export default {
  components: { VolBox },
  data() {
    return {
      showDetialBox: false,
      robotList: [
        { robotCode: '注液组盘机械手', robotName: '注液组盘机械手' },
        { robotCode: '高温换盘机械手', robotName: '高温换盘机械手' },
        { robotCode: '化成换盘机械手', robotName: '化成换盘机械手' },
        { robotCode: '拆盘机械手', robotName: '拆盘机械手' },
        { robotCode: '成品组盘机械手', robotName: '成品组盘机械手' }
      ],
      selectedRobot: '',
      currentRow: null,
      actionType: null // 'bind' or 'unbind'
    };
  },
  methods: {
    open(action, row) {
      this.actionType = action;
      this.currentRow = row;
      this.selectedRobot = '';
      this.showDetialBox = true;
    },
    close() {
      this.showDetialBox = false;
    },
    async submit() {
      if (!this.selectedRobot) {
        return this.$message.error("请选择机械手");
      }
      this.showDetialBox = false;
      try {
        if (this.actionType === 'bind') {
          // ç»„盘确认
          await this.$confirm(
            `确认执行托盘组盘操作?\n托盘编号:${this.currentRow.palletCode}\n机械手:${this.selectedRobot}`,
            "组盘确认",
            {
              confirmButtonText: "确认",
              cancelButtonText: "取消",
              type: "warning"
            }
          );
          const result = await this.http.post("/api/StockInfoDetail/BindContainer", {
            palletCode: this.currentRow.palletCode,
            robotCode: this.selectedRobot
          }, "正在调用MES接口...");
          if (result.status) {
            this.$Message.success(result.message || "托盘组盘成功");
            this.$parent.$refs.table.load();
          } else {
            this.$error(result.message || "托盘组盘失败");
          }
        } else if (this.actionType === 'unbind') {
          // æ‹†ç›˜ç¡®è®¤
          await this.$confirm(
            `确认执行托盘拆盘操作?\n托盘编号:${this.currentRow.palletCode}\n机械手:${this.selectedRobot}`,
            "拆盘确认",
            {
              confirmButtonText: "确认",
              cancelButtonText: "取消",
              type: "warning"
            }
          );
          const result = await this.http.post("/api/StockInfoDetail/UnbindContainer", {
            palletCode: this.currentRow.palletCode,
            robotCode: this.selectedRobot
          }, "正在调用MES接口...");
          if (result.status) {
            this.$Message.success(result.message || "托盘拆盘成功");
            this.$parent.$refs.table.load();
          } else {
            this.$error(result.message || "托盘拆盘失败");
          }
        }
      } catch (error) {
        if (error !== "cancel") {
          this.$error(error.message || "网络错误,请稍后重试");
        }
      }
    }
  }
};
</script>
Code/WMS/WIDESEA_WMSClient/src/extension/stock/stockInfo.jsx
@@ -1,11 +1,12 @@
//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码
import RobotSelect from './extend/RobotSelect.vue';
let extension = {
  components: {
    //查询界面扩展组件
    gridHeader: "",
    gridBody: "",
    gridFooter: "",
    gridHeader: '',
    gridBody: RobotSelect,
    gridFooter: '',
    //新建、编辑弹出框扩展组件
    modelHeader: "",
    modelBody: "",
@@ -28,26 +29,34 @@
              <el-button
                type="primary"
                size="small"
                onClick={($e) => {
                  this.handleInbound(row);
                }}
              >
                è¿›ç«™
              </el-button>
                onClick={($e) => { this.handleBind(row); }}
              >绑定</el-button>
              <el-button
                type="primary"
                size="small"
                onClick={($e) => { this.handleInbound(row); }}
              >进站</el-button>
              <el-button
                type="success"
                size="small"
                style="margin-left: 8px"
                onClick={($e) => {
                  this.handleOutbound(row);
                }}
              >
                å‡ºç«™
              </el-button>
                onClick={($e) => { this.handleOutbound(row); }}
              >出站</el-button>
              <el-button
                type="success"
                size="small"
                style="margin-left: 8px"
                onClick={($e) => { this.handleUnbind(row); }}
              >解绑</el-button>
            </div>
          );
        },
      });
    },
    // æ‰˜ç›˜ç»„盘操作
    handleBind(row) {
      this.$refs.gridBody.open('bind', row);
    },
    // æ‰˜ç›˜è¿›ç«™æ“ä½œ
@@ -120,6 +129,11 @@
      }
    },
    // æ‰˜ç›˜æ‹†ç›˜æ“ä½œ
    handleUnbind(row) {
      this.$refs.gridBody.open('unbind', row);
    },
    onInited() {
      // æ¡†æž¶åˆå§‹åŒ–配置后
    },
Code/WMS/WIDESEA_WMSClient/src/extension/system/Mes_Log.jsx
@@ -48,13 +48,15 @@
        this.showJsonDetail(row, 'request');
      } else if (column.property === 'responseJson' && row.responseJson) {
        this.showJsonDetail(row, 'response');
      } else if (column.property === 'errorMessage' && row.errorMessage) {
        this.showJsonDetail(row, 'errorMessage');
      }
    },
    // æ˜¾ç¤º JSON è¯¦æƒ…抽屉
    showJsonDetail(row, type = 'request') {
      const jsonContent = type === 'request' ? row.requestJson : row.responseJson;
      const title = type === 'request' ? '📋 è¯·æ±‚ JSON' : '📥 å“åº” JSON';
      const jsonContent = type === 'request' ? row.requestJson :  type === 'response' ? row.responseJson : row.errorMessage;
      const title = type === 'request' ? '📋 è¯·æ±‚ JSON' : type === 'response' ? '📋 è¯·æ±‚ JSON': '📥 é”™è¯¯æ¶ˆæ¯';
      // è§£æž JSON å¯¹è±¡ï¼Œè§£æžå¤±è´¥åˆ™ä¿ç•™åŽŸå§‹å­—ç¬¦ä¸²
      let jsonData;
Code/WMS/WIDESEA_WMSClient/src/views/system/Mes_Log.vue
@@ -81,7 +81,19 @@
          return `<span style="color: #409EFF; cursor: pointer;">${preview}</span>`;
        }
      },
      { field: "errorMessage", title: "错误信息", width: 250 },
      {
        field: "errorMessage",
        title: "错误信息",
        width: 250,
        formatter: (row) => {
          if (!row.responseJson) return '-';
          const preview = row.responseJson.length > 50
            ? row.responseJson.substring(0, 50) + '...'
            : row.responseJson;
          return `<span style="color: #409EFF; cursor: pointer;">${preview}</span>`;
        }
      },
      { field: "elapsedMs", title: "耗时(ms)", width: 100, sortable: true },
      { field: "createDate", title: "调用时间", width: 160, sortable: true },
      { field: "creator", title: "操作人", width: 100 }
Code/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/MesService.cs
@@ -43,7 +43,7 @@
            };
        }
        private HttpRequestConfig BuildConfig(string token)
        public HttpRequestConfig BuildConfig(string token)
        {
            return new HttpRequestConfig
            {
Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/Filter/ApiAuthorizeFilter.cs
@@ -84,7 +84,7 @@
                int ExpMinutes = AppSettings.Get("ExpMinutes").ObjToInt();
                if ((expDate.GetValueOrDefault() - DateTime.Now).TotalMinutes < ExpMinutes / 3 && context.HttpContext.Request.Path != ReplaceTokenPath)
                {
                    context.HttpContext.Response.Headers.Add("widesea_exp", "1");
                    context.HttpContext.Response.Headers.Append("widesea_exp", "1");
                }
            }
Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/Middlewares/HttpRequestMiddleware.cs
@@ -18,7 +18,7 @@
        public async Task InvokeAsync(HttpContext context)
        {
            context.Response.Headers.Add("Access-Control-Expose-Headers", "widesea_exp");
            context.Response.Headers.Append("Access-Control-Expose-Headers", "widesea_exp");
            await _next(context);
        }
    }
Code/WMS/WIDESEA_WMSServer/WIDESEA_DTO/MES/BindContainerRequestDto.cs
@@ -18,6 +18,11 @@
        public List<string> SfcList { get; set; }
        /// <summary>
        /// è®¾å¤‡åç§°
        /// </summary>
        public string DeviceName { get; set; }
        /// <summary>
        /// ä½ç½®ä¿¡æ¯
        /// </summary>
        public string Location { get; set; }
Code/WMS/WIDESEA_WMSServer/WIDESEA_DTO/MES/UnbindContainerRequestDto.cs
@@ -13,6 +13,11 @@
        public string PalletCode { get; set; }
        /// <summary>
        /// è®¾å¤‡åç§°
        /// </summary>
        public string DeviceName { get; set; }
        /// <summary>
        /// ç”µèŠ¯ç åˆ—è¡¨
        /// </summary>
        public List<string> SfcList { get; set; }
Code/WMS/WIDESEA_WMSServer/WIDESEA_IBasicService/IMesService.cs
@@ -53,5 +53,12 @@
        /// æ‰˜ç›˜å‡ºç«™ï¼ˆæ”¯æŒåŠ¨æ€Token)
        /// </summary>
        HttpResponseResult<MesResponse> OutboundInContainer(OutboundInContainerRequest request, string token);
        /// <summary>
        ///  è¯·æ±‚头配置
        /// </summary>
        /// <param name="token"> è¯·æ±‚Token</param>
        /// <returns></returns>
        HttpRequestConfig BuildConfig(string token);
    }
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_IBasicService/IMesUploadHelper.cs
@@ -22,7 +22,7 @@
            MesUploadStatusEnum successStatus,
            string apiType,
            string requestJson,
            Func<(bool isSuccess, string responseJson, string errorMessage)> mesCall,
            Func<(bool isSuccess, string responseJson, string errorMessage, string httpRequest)> mesCall,
            string creator = "System");
    }
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/MesUploadHelper.cs
@@ -1,9 +1,10 @@
using Newtonsoft.Json.Linq;
using System.Diagnostics;
using WIDESEA_Common.StockEnum;
using WIDESEA_Core;
using WIDESEA_DTO.MES;
using WIDESEA_IStockService;
using WIDESEA_IBasicService;
using WIDESEA_IStockService;
namespace WIDESEA_StockService
{
@@ -34,7 +35,7 @@
            MesUploadStatusEnum successStatus,
            string apiType,
            string requestJson,
            Func<(bool isSuccess, string responseJson, string errorMessage)> mesCall,
            Func<(bool isSuccess, string responseJson, string errorMessage, string httpRequest)> mesCall,
            string creator = "System")
        {
            _ = Task.Run(async () =>
@@ -42,12 +43,14 @@
                var stopwatch = Stopwatch.StartNew();
                try
                {
                    var (isSuccess, responseJson, errorMessage) = mesCall();
                    var (isSuccess, responseJson, errorMessage, httpRequest) = mesCall();
                    stopwatch.Stop();
                    // å¥‡æ•°=成功,偶数=失败
                    int status = isSuccess ? (int)successStatus : (int)successStatus + 1;
                    await _stockInfoService.UpdateMesUploadStatusAsync(palletCode, status);
                    requestJson = MergeJsonObjects(requestJson, httpRequest);
                    await LogAsync(palletCode, apiType, requestJson, responseJson,
                        stopwatch.ElapsedMilliseconds, isSuccess, errorMessage, creator);
@@ -89,5 +92,16 @@
                // æ—¥å¿—记录失败不影响主流程
            }
        }
        public static string MergeJsonObjects(string json1, string json2)
        {
            var obj1 = JObject.Parse(json1);
            var obj2 = JObject.Parse(json2);
            obj1.Merge(obj2, new JsonMergeSettings
            {
                MergeArrayHandling = MergeArrayHandling.Union   // æ•°ç»„合并方式,可按需修改
            });
            return obj1.ToString();
        }
    }
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs
@@ -463,7 +463,8 @@
                        return (
                            result?.Data?.IsSuccess ?? false,
                            System.Text.Json.JsonSerializer.Serialize(result),
                            result?.Data?.Msg ?? result?.ErrorMessage ?? "未知错误"
                            result?.Data?.Msg ?? result?.ErrorMessage ?? "未知错误",
                            _mesService.BuildConfig(token ?? string.Empty).ToJson()
                        );
                    });
@@ -548,7 +549,8 @@
                        return (
                            result?.Data?.IsSuccess ?? false,
                            System.Text.Json.JsonSerializer.Serialize(result),
                            result?.Data?.Msg ?? result?.ErrorMessage ?? "未知错误"
                            result?.Data?.Msg ?? result?.ErrorMessage ?? "未知错误",
                            _mesService.BuildConfig(token ?? string.Empty).ToJson()
                        );
                    });
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WCS/TaskService_Inbound.cs
@@ -206,7 +206,8 @@
                                return (
                                    result?.Data?.IsSuccess ?? false,
                                    JsonConvert.SerializeObject(result),
                                    result?.Data?.Msg ?? result?.ErrorMessage ?? "未知错误"
                                    result?.Data?.Msg ?? result?.ErrorMessage ?? "未知错误",
                                    _mesService.BuildConfig(token ?? string.Empty).ToJson()
                                );
                            });
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WCS/TaskService_Outbound.cs
@@ -153,7 +153,8 @@
                            return (
                                result?.Data?.IsSuccess ?? false,
                                Newtonsoft.Json.JsonConvert.SerializeObject(result),
                                result?.Data?.Msg ?? result?.ErrorMessage ?? "未知错误"
                                result?.Data?.Msg ?? result?.ErrorMessage ?? "未知错误",
                                _mesService.BuildConfig(token ?? string.Empty).ToJson()
                            );
                        });
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockInfoController.cs
@@ -11,6 +11,7 @@
using WIDESEA_Model.Models;
using WIDESEA_Common.Constants;
using WIDESEA_Common.StockEnum;
using WIDESEA_Core.Helper;
namespace WIDESEA_WMSServer.Controllers.Stock
{
@@ -113,9 +114,10 @@
                            ? _mesService.InboundInContainer(mesRequest)
                            : _mesService.InboundInContainer(mesRequest, token);
                        return (
                            result?.IsSuccess ?? false,
                            result.Data?.IsSuccess ?? false,
                            System.Text.Json.JsonSerializer.Serialize(result),
                            result?.ErrorMessage ?? "未知错误"
                            result?.Data?.Msg ?? result?.ErrorMessage ?? "未知错误",
                            _mesService.BuildConfig(token ?? string.Empty).ToJson()
                        );
                    },
                    App.User.UserName);
@@ -203,9 +205,10 @@
                            ? _mesService.OutboundInContainer(mesRequest)
                            : _mesService.OutboundInContainer(mesRequest, token);
                        return (
                            result?.IsSuccess ?? false,
                            result?.Data?.IsSuccess ?? false,
                            System.Text.Json.JsonSerializer.Serialize(result),
                            result?.ErrorMessage ?? "未知错误"
                            result?.Data?.Msg ?? result?.ErrorMessage ?? "未知错误",
                            _mesService.BuildConfig(token ?? string.Empty).ToJson()
                        );
                    },
                    App.User.UserName);
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockInfoDetailController.cs
@@ -1,14 +1,14 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using WIDESEA_Core;
using WIDESEA_Core.BaseController;
using WIDESEA_DTO.MES;
using WIDESEA_IStockService;
using WIDESEA_IBasicService;
using WIDESEA_ISystemService;
using WIDESEA_Model.Models;
using Microsoft.AspNetCore.Mvc;
using WIDESEA_Common.Constants;
using WIDESEA_Common.StockEnum;
using WIDESEA_Core;
using WIDESEA_Core.BaseController;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.MES;
using WIDESEA_IBasicService;
using WIDESEA_IStockService;
using WIDESEA_ISystemService;
using WIDESEA_Model.Models;
namespace WIDESEA_WMSServer.Controllers.Stock
{
@@ -52,22 +52,22 @@
            try
            {
                // 1. å‚数验证
                if (dto.SfcList == null || !dto.SfcList.Any())
                {
                    return response.Error("电芯码列表不能为空");
                }
                //// 1. å‚数验证
                //if (dto.SfcList == null || !dto.SfcList.Any())
                //{
                //    return response.Error("电芯码列表不能为空");
                //}
                // 2. éªŒè¯ç”µèŠ¯çŠ¶æ€ï¼ˆéž'已锁定'状态允许绑定)
                var stockDetail = await Service.Repository.QueryFirstAsync(x => dto.SfcList.Contains(x.SerialNumber));
                if (stockDetail != null && stockDetail.Status == 99)
                {
                    return response.Error("当前库存明细包含已锁定状态,不允许执行绑定操作");
                }
                var stockInfo = await _stockInfoService.Repository.QueryFirstAsync(x => stockDetail.StockId == x.Id);
                //var stockDetail = await Service.Repository.QueryFirstAsync(x => dto.SfcList.Contains(x.SerialNumber));
                //if (stockDetail != null && stockDetail.Status == 99)
                //{
                //    return response.Error("当前库存明细包含已锁定状态,不允许执行绑定操作");
                //}
                var stockInfo = await _stockInfoService.Repository.QueryDataNavFirstAsync(x => x.PalletCode == dto.PalletCode);
                // 3. åŠ¨æ€èŽ·å–MES凭证
                var mesConfig = _mesDeviceConfigService.GetByDeviceName("组盘机械手");
                var mesConfig = _mesDeviceConfigService.GetByDeviceName(dto.DeviceName);
                string equipmentCode = mesConfig?.EquipmentCode ?? StockConstants.MES_EQUIPMENT_CODE;
                string resourceCode = mesConfig?.ResourceCode ?? StockConstants.MES_RESOURCE_CODE;
                string token = mesConfig?.Token;
@@ -79,10 +79,10 @@
                    ResourceCode = resourceCode,
                    LocalTime = DateTime.Now,
                    ContainerCode = stockInfo.PalletCode,
                    ContainerSfcList = dto.SfcList.Select(sfc => new ContainerSfcItem
                    ContainerSfcList = stockInfo.Details.Select(sfc => new ContainerSfcItem
                    {
                        Sfc = sfc,
                        Location = dto.Location ?? ""
                        Sfc = sfc.SerialNumber,
                        Location = sfc.InboundOrderRowNo.ToString() ?? ""
                    }).ToList(),
                    OperationType = dto.OperationType
                };
@@ -101,9 +101,10 @@
                            ? _mesService.BindContainer(mesRequest)
                            : _mesService.BindContainer(mesRequest, token);
                        return (
                            result?.IsSuccess ?? false,
                            result?.Data?.IsSuccess ?? false,
                            System.Text.Json.JsonSerializer.Serialize(result),
                            result?.ErrorMessage ?? "未知错误"
                            result?.Data?.Msg ?? result?.ErrorMessage ?? "未知错误",
                            _mesService.BuildConfig(token ?? string.Empty).ToJson()
                        );
                    },
                    App.User.UserName);
@@ -130,21 +131,21 @@
            try
            {
                // 1. å‚数验证
                if (dto.SfcList == null || !dto.SfcList.Any())
                {
                    return response.Error("电芯码列表不能为空");
                }
                //if (dto.SfcList == null || !dto.SfcList.Any())
                //{
                //    return response.Error("电芯码列表不能为空");
                //}
                // 2. éªŒè¯ç”µèŠ¯çŠ¶æ€ï¼ˆéž'已锁定'状态允许解绑)
                var stockDetail = await Service.Repository.QueryFirstAsync(x => dto.SfcList.Contains(x.SerialNumber));
                if (stockDetail != null && stockDetail.Status == 99)
                {
                    return response.Error("当前库存明细包含已锁定状态,不允许执行解绑操作");
                }
                var stockInfo = await _stockInfoService.Repository.QueryFirstAsync(x => stockDetail.StockId == x.Id);
                //// 2. éªŒè¯ç”µèŠ¯çŠ¶æ€ï¼ˆéž'已锁定'状态允许解绑)
                //var stockDetail = await Service.Repository.QueryFirstAsync(x => dto.SfcList.Contains(x.SerialNumber));
                //if (stockDetail != null && stockDetail.Status == 99)
                //{
                //    return response.Error("当前库存明细包含已锁定状态,不允许执行解绑操作");
                //}
                var stockInfo = await _stockInfoService.Repository.QueryDataNavFirstAsync(x => dto.PalletCode == x.PalletCode);
                // 3. åŠ¨æ€èŽ·å–MES凭证
                var mesConfig = _mesDeviceConfigService.GetByDeviceName("组盘机械手");
                var mesConfig = _mesDeviceConfigService.GetByDeviceName(dto.DeviceName);
                string equipmentCode = mesConfig?.EquipmentCode ?? StockConstants.MES_EQUIPMENT_CODE;
                string resourceCode = mesConfig?.ResourceCode ?? StockConstants.MES_RESOURCE_CODE;
                string token = mesConfig?.Token;
@@ -156,7 +157,7 @@
                    ResourceCode = resourceCode,
                    LocalTime = DateTime.Now,
                    ContainCode = stockInfo.PalletCode,
                    SfcList = dto.SfcList
                    SfcList = stockInfo.Details.Select(x => x.SerialNumber).ToList(),
                };
                string requestJson = System.Text.Json.JsonSerializer.Serialize(mesRequest);
@@ -173,9 +174,10 @@
                            ? _mesService.UnBindContainer(mesRequest)
                            : _mesService.UnBindContainer(mesRequest, token);
                        return (
                            result?.IsSuccess ?? false,
                            result?.Data?.IsSuccess ?? false,
                            System.Text.Json.JsonSerializer.Serialize(result),
                            result?.ErrorMessage ?? "未知错误"
                            result?.Data?.Msg ?? result?.ErrorMessage ?? "未知错误",
                            _mesService.BuildConfig(token ?? string.Empty).ToJson()
                        );
                    },
                    App.User.UserName);
@@ -254,9 +256,10 @@
                    {
                        var result = _mesService.ContainerNgReport(mesRequest);
                        return (
                            result?.IsSuccess ?? false,
                            result?.Data?.IsSuccess ?? false,
                            System.Text.Json.JsonSerializer.Serialize(result),
                            result?.ErrorMessage ?? "未知错误"
                            result?.Data?.Msg ?? result?.ErrorMessage ?? "未知错误",
                            _mesService.BuildConfig(mesConfig?.Token ?? string.Empty).ToJson()
                        );
                    },
                    App.User.UserName);