refactor: 统一日志组件为Serilog并优化相关功能
feat(StockInfoDetail): 新增托盘绑定和解绑功能
fix: 修复跨域配置和HTTP头设置问题
perf(ConveyorLineNewJob): 添加托盘检查间隔限制优化性能
style: 清理无用引用和格式化代码
| | |
| | | .Enrich.WithProperty("Application", "WCS") |
| | | // 设置Microsoft命名空间的日志级别为Information |
| | | // 这样可以减少Microsoft框架本身的详细日志,避免过多的Debug日志 |
| | | .MinimumLevel.Override("Microsoft", LogEventLevel.Information) |
| | | .MinimumLevel.Override("Microsoft", LogEventLevel.Debug) |
| | | .WriteTo.Console() // 添加控制台输出接收器,日志将显示在控制台窗口中 |
| | | // 添加文件输出接收器,将日志写入文件系统 |
| | | .WriteTo.File( |
| | |
| | | //跨域 |
| | | "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" |
| | |
| | | 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; |
| | |
| | | /// 任务服务 |
| | | /// </summary> |
| | | private readonly ITaskService _taskService; |
| | | |
| | | |
| | | /// <summary> |
| | | /// 机器人任务服务 |
| | |
| | | /// <summary> |
| | | /// 日志记录器 |
| | | /// </summary> |
| | | private readonly ILogger<CommonConveyorLineNewJob> _logger; |
| | | private readonly ILogger _logger; |
| | | |
| | | /// <summary> |
| | | /// 目标地址到设备类型的映射 |
| | |
| | | /// <remarks> |
| | | /// </remarks> |
| | | private static List<string> AddressToDeviceType = new List<string> { "11020", "11028" }; |
| | | |
| | | /// <summary> |
| | | /// 托盘检查位置的最近执行时间(用于30秒间隔限制) |
| | | /// </summary> |
| | | private static readonly Dictionary<string, DateTime> _lastPalletCheckTime = new(); |
| | | |
| | | /// <summary> |
| | | /// 构造函数 |
| | |
| | | /// <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; |
| | |
| | | // 如果当前设备在检查列表中 |
| | | 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) |
| | | { |
| | |
| | | TargetAddress = childDeviceCode |
| | | }.Serialize()); |
| | | |
| | | _lastPalletCheckTime[childDeviceCode] = DateTime.Now; |
| | | |
| | | // 如果请求成功,接收 WMS 返回的任务 |
| | | if (responseResult.IsSuccess && responseResult.Data.Status) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | #endregion |
| | | #endregion 检测是否需要空托盘 |
| | | |
| | | // ========== 检查 PLC_STB 标志 ========== |
| | | // 只有当 PLC_STB 为 1 时才处理任务 |
| | |
| | | RobotTargetAddressLineCode = childDeviceCode, |
| | | RobotTaskNum = num, // 生成任务号 |
| | | RobotDispatchertime = DateTime.Now, |
| | | |
| | | }; |
| | | if (_robotTaskService.AddData(robotTask).Status) |
| | | { |
| | |
| | | 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; |
| | |
| | | Dt_Task? task = _taskFilter.QueryExecutingTask(command.TaskNo, childDeviceCode); |
| | | if (task != null) |
| | | { |
| | | |
| | | // 更新任务状态到下一阶段(通常是完成) |
| | | if (_taskService.UpdateTaskStatusToNext(task).Status) |
| | | { |
| | |
| | | conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode); |
| | | QuartzLogHelper.LogInfo(_logger, "ConveyorLineInFinish:入库完成,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"入库完成,任务号: {task.TaskNum}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode); |
| | | } |
| | | |
| | | |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | using Microsoft.Extensions.Logging; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | using Serilog; |
| | | using WIDESEAWCS_QuartzJob; |
| | | |
| | | namespace WIDESEAWCS_Tasks |
| | |
| | | if (device == null) |
| | | { |
| | | // 设备未找到时记录调试日志,方便排查配置问题 |
| | | _logger.LogDebug("FindDevice:未找到 {DeviceName}", deviceName); |
| | | _logger.Debug("FindDevice:未找到 {DeviceName}", deviceName); |
| | | } |
| | | return device; // 可能为 null,由调用方负责 null 检查 |
| | | } |
| | |
| | | QuartzLogHelper.LogDebug(_logger, "Handle{Scenario}:子设备: {ChildDeviceCode},目标地址: {NextAddress}", $"Handle{scenario}:子设备: {childDeviceCode},目标地址: {nextAddress}", conveyorLine.DeviceCode, scenario, childDeviceCode, nextAddress); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | using Microsoft.Extensions.Logging; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | using Serilog; |
| | | using WIDESEAWCS_ITaskInfoService; |
| | | using WIDESEAWCS_Model.Models; |
| | | |
| | |
| | | return result.Status; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | using Microsoft.Extensions.Logging; |
| | | using Serilog; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | |
| | | namespace WIDESEAWCS_Tasks; |
| | |
| | | /// <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); |
| | | } |
| | | |
| | |
| | | /// <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); |
| | | } |
| | | |
| | |
| | | /// <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> |
| | |
| | | /// <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); |
| | | } |
| | | |
| | |
| | | /// <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); |
| | | } |
| | | } |
| | | } |
| | |
| | | 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; |
| | |
| | | using WIDESEAWCS_QuartzJob.Service; |
| | | using WIDESEAWCS_QuartzJob.StackerCrane; |
| | | using WIDESEAWCS_QuartzJob.StackerCrane.Enum; |
| | | using WIDESEAWCS_Common.Constants; |
| | | using WIDESEAWCS_Tasks.StackerCraneJob; |
| | | |
| | | namespace WIDESEAWCS_Tasks |
| | |
| | | /// <summary> |
| | | /// 日志记录器 |
| | | /// </summary> |
| | | private readonly ILogger<CommonStackerCraneJob> _logger; |
| | | private readonly ILogger _logger; |
| | | |
| | | /// <summary> |
| | | /// 堆垛机设备编码 |
| | |
| | | ITaskRepository taskRepository, |
| | | IRouterService routerService, |
| | | HttpClientHelper httpClientHelper, |
| | | ILogger<CommonStackerCraneJob> logger) |
| | | ILogger logger) |
| | | { |
| | | _taskService = taskService; |
| | | _taskExecuteDetailService = taskExecuteDetailService; |
| | |
| | | { |
| | | 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; |
| | |
| | | |
| | | // ========== 检查是否可以发送新任务 ========== |
| | | //if (!commonStackerCrane.IsCanSendTask(commonStackerCrane.Communicator, commonStackerCrane.DeviceProDTOs, commonStackerCrane.DeviceProtocolDetailDTOs)) |
| | | if (commonStackerCrane.StackerCraneStatusValue != StackerCraneStatus.Normal ) |
| | | if (commonStackerCrane.StackerCraneStatusValue != StackerCraneStatus.Normal) |
| | | { |
| | | // 堆垛机不可用(如正在执行上一任务),直接返回 |
| | | return Task.CompletedTask; |
| | |
| | | // 记录异常 |
| | | QuartzLogHelper.LogError(_logger, ex, "Execute:执行异常,设备: {DeviceCode}", $"执行异常: {ex.Message}", _deviceCode, _deviceCode); |
| | | } |
| | | finally |
| | | { |
| | | QuartzLogHelper.LogInfo(_logger, $"CommonStackerCraneJob Execute:堆垛机任务调度执行完成 【{DateTime.Now.ToString("F")}】", _deviceCode); |
| | | } |
| | | |
| | | return Task.CompletedTask; |
| | | } |
| | |
| | | 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; |
| | |
| | | /// <returns>堆垛机命令对象,转换失败返回 null</returns> |
| | | public object? ConvertToStackerCraneTaskCommand([NotNull] Dt_Task task) |
| | | { |
| | | return BuildCommand(task, CreateStandardCommand(task)); |
| | | return BuildCommand(task, CreateStandardCommand(task)); |
| | | // 根据巷道获取命令类型 |
| | | //string commandType = GetCommandType(task.Roadway); |
| | | |
| | |
| | | { |
| | | taskType = StackerCraneConst.EmptyPalletTaskType; |
| | | } |
| | | else if(task.TaskType == (int)TaskInboundTypeEnum.InEmpty) |
| | | else if (task.TaskType == (int)TaskInboundTypeEnum.InEmpty) |
| | | { |
| | | taskType = StackerCraneConst.EmptyInPalletTaskType; |
| | | } |
| | |
| | | && short.TryParse(parts[2], out layer); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | 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; |
| | |
| | | return isOccupied; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | 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; |
| | |
| | | <el-button |
| | | type="primary" |
| | | size="small" |
| | | onClick={($e) => { this.handleBind(row); }} |
| | | >绑定</el-button> |
| | | <el-button |
| | | type="primary" |
| | | size="small" |
| | | onClick={($e) => { this.handleInbound(row); }} |
| | | >进站</el-button> |
| | | <el-button |
| | |
| | | style="margin-left: 8px" |
| | | 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> |
| | | ); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // 托盘组盘操作 |
| | | async handleBind(row) { |
| | | try { |
| | | await this.$confirm(`确认执行托盘组盘操作?\n托盘编号:${row.palletCode}`, "组盘确认", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning" |
| | | }); |
| | | |
| | | const result = await this.http.post("/api/StockInfoDetail/BindContainer", { |
| | | palletCode: row.palletCode |
| | | }, "正在调用MES接口..."); |
| | | |
| | | if (result.status) { |
| | | this.$Message.success(result.message || "托盘组盘成功"); |
| | | this.$refs.table.load(); |
| | | } else { |
| | | this.$error(result.message || "托盘组盘失败"); |
| | | } |
| | | } catch (error) { |
| | | if (error !== "cancel") { |
| | | this.$error(error.message || "网络错误,请稍后重试"); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // 托盘进站操作 |
| | |
| | | } |
| | | }, |
| | | |
| | | // 托盘拆盘操作 |
| | | async handleUnbind(row) { |
| | | try { |
| | | await this.$confirm(`确认执行托盘拆盘操作?\n托盘编号:${row.palletCode}`, "拆盘确认", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning" |
| | | }); |
| | | |
| | | const result = await this.http.post("/api/StockInfoDetail/UnbindContainer", { |
| | | palletCode: row.palletCode, |
| | | }, "正在调用MES接口..."); |
| | | |
| | | if (result.status) { |
| | | this.$Message.success(result.message || "托盘拆盘成功"); |
| | | this.$refs.table.load(); |
| | | } else { |
| | | this.$error(result.message || "托盘拆盘失败"); |
| | | } |
| | | } catch (error) { |
| | | if (error !== "cancel") { |
| | | this.$error(error.message || "网络错误,请稍后重试"); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | onInited() { |
| | | // 框架初始化配置后 |
| | | }, |
| | |
| | | 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; |
| | |
| | | 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 } |
| | |
| | | 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"); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | 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); |
| | | } |
| | | } |
| | |
| | | ? _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 ?? "未知错误" |
| | | ); |
| | | }, |
| | | App.User.UserName); |
| | |
| | | ? _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 ?? "未知错误" |
| | | ); |
| | | }, |
| | | App.User.UserName); |
| | |
| | | using Microsoft.AspNetCore.Http; |
| | | using Microsoft.AspNetCore.Mvc; |
| | | using Microsoft.AspNetCore.Mvc; |
| | | using WIDESEA_Common.Constants; |
| | | using WIDESEA_Common.StockEnum; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseController; |
| | | using WIDESEA_DTO.MES; |
| | | using WIDESEA_IStockService; |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_IStockService; |
| | | using WIDESEA_ISystemService; |
| | | using WIDESEA_Model.Models; |
| | | using WIDESEA_Common.Constants; |
| | | using WIDESEA_Common.StockEnum; |
| | | |
| | | namespace WIDESEA_WMSServer.Controllers.Stock |
| | | { |
| | |
| | | |
| | | 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("组盘机械手"); |
| | |
| | | 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 |
| | | }; |
| | |
| | | ? _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 ?? "未知错误" |
| | | ); |
| | | }, |
| | | App.User.UserName); |
| | |
| | | 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("组盘机械手"); |
| | |
| | | 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); |
| | |
| | | ? _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 ?? "未知错误" |
| | | ); |
| | | }, |
| | | App.User.UserName); |
| | |
| | | return defaultValue; |
| | | } |
| | | } |
| | | } |
| | | } |