wanshenmean
13 小时以前 c5c3e4e538a11f2a6391e6b2613375b1f92eb20a
feat: 添加Quartz日志助手类并重构任务服务日志记录

refactor(任务服务): 统一ILogger和QuartzLogger的日志记录方式
fix(任务枚举): 修正空箱入库任务类型值
feat(任务流服务): 初始化方法增加返回值以处理错误
style(前端): 调整任务状态显示逻辑和样式
chore: 更新模拟器配置文件和忽略文件
已添加3个文件
已修改27个文件
944 ■■■■■ 文件已修改
.gitignore 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/.omc/state/agent-replay-cf22b2af-f777-4b1d-beca-2152d6beebbb.jsonl 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/.omc/state/idle-notif-cooldown.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/.omc/state/mission-state.json 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/.omc/state/subagent-tracking.json 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Client/.omc/project-memory.json 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IInboundTaskFlowService.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IOutboundTaskFlowService.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRelocationTaskFlowService.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotTaskFlowService.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/InboundTaskFlowService.cs 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/RelocationTaskFlowService.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/RobotTaskFlowService.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/CommonConveyorLineNewJob.cs 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTaskFilter.cs 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/QuartzLogHelper.cs 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/CommonStackerCraneJob.cs 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneCommandBuilder.cs 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/extension/taskinfo/extend/gridBodyExtension.vue 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/TaskEnum/TaskTypeEnum.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/测试工具/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Data/instance-1003/config.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/测试工具/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Data/instance-CWSC1/config.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/测试工具/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Data/instance-HCSC1/config.json 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/测试工具/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Data/instance-PM/config.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/测试工具/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Data/protocol-templates.json 316 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -439,3 +439,5 @@
**/.claude/settings.local.json
**/.vs/**/DocumentLayout.json
**/.vs/**/DocumentLayout.backup.json
/Code/测试工具/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Data
/Code/测试工具/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Data
Code/.omc/state/agent-replay-cf22b2af-f777-4b1d-beca-2152d6beebbb.jsonl
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,2 @@
{"t":0,"agent":"a48e41d","agent_type":"Explore","event":"agent_start","parent_mode":"none"}
{"t":0,"agent":"a48e41d","agent_type":"Explore","event":"agent_stop","success":true,"duration_ms":51400}
Code/.omc/state/idle-notif-cooldown.json
@@ -1,3 +1,3 @@
{
  "lastSentAt": "2026-04-14T08:08:15.956Z"
  "lastSentAt": "2026-04-15T06:28:49.381Z"
}
Code/.omc/state/mission-state.json
@@ -1,5 +1,5 @@
{
  "updatedAt": "2026-04-13T02:47:35.467Z",
  "updatedAt": "2026-04-15T06:10:46.493Z",
  "missions": [
    {
      "id": "session:9007b9ea-1eb6-4d24-8fe7-2c3a949eac88:none",
@@ -428,6 +428,54 @@
          "sourceKey": "session-stop:adb1029c24100db60"
        }
      ]
    },
    {
      "id": "session:cf22b2af-f777-4b1d-beca-2152d6beebbb:none",
      "source": "session",
      "name": "none",
      "objective": "Session mission",
      "createdAt": "2026-04-15T06:09:55.093Z",
      "updatedAt": "2026-04-15T06:10:46.493Z",
      "status": "done",
      "workerCount": 1,
      "taskCounts": {
        "total": 1,
        "pending": 0,
        "blocked": 0,
        "inProgress": 0,
        "completed": 1,
        "failed": 0
      },
      "agents": [
        {
          "name": "Explore:a48e41d",
          "role": "Explore",
          "ownership": "a48e41df38204e6dc",
          "status": "done",
          "currentStep": null,
          "latestUpdate": "completed",
          "completedSummary": null,
          "updatedAt": "2026-04-15T06:10:46.493Z"
        }
      ],
      "timeline": [
        {
          "id": "session-start:a48e41df38204e6dc:2026-04-15T06:09:55.093Z",
          "at": "2026-04-15T06:09:55.093Z",
          "kind": "update",
          "agent": "Explore:a48e41d",
          "detail": "started Explore:a48e41d",
          "sourceKey": "session-start:a48e41df38204e6dc"
        },
        {
          "id": "session-stop:a48e41df38204e6dc:2026-04-15T06:10:46.493Z",
          "at": "2026-04-15T06:10:46.493Z",
          "kind": "completion",
          "agent": "Explore:a48e41d",
          "detail": "completed",
          "sourceKey": "session-stop:a48e41df38204e6dc"
        }
      ]
    }
  ]
}
Code/.omc/state/subagent-tracking.json
@@ -287,10 +287,19 @@
      "status": "completed",
      "completed_at": "2026-04-13T02:47:35.467Z",
      "duration_ms": 9005
    },
    {
      "agent_id": "a48e41df38204e6dc",
      "agent_type": "Explore",
      "started_at": "2026-04-15T06:09:55.093Z",
      "parent_mode": "none",
      "status": "completed",
      "completed_at": "2026-04-15T06:10:46.493Z",
      "duration_ms": 51400
    }
  ],
  "total_spawned": 32,
  "total_completed": 32,
  "total_spawned": 33,
  "total_completed": 33,
  "total_failed": 0,
  "last_updated": "2026-04-13T02:47:35.573Z"
  "last_updated": "2026-04-15T06:10:46.596Z"
}
Code/WCS/WIDESEAWCS_Client/.omc/project-memory.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,182 @@
{
  "version": "1.0.0",
  "lastScanned": 1776214627595,
  "projectRoot": "d:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Client",
  "techStack": {
    "languages": [
      {
        "name": "JavaScript/TypeScript",
        "version": null,
        "confidence": "high",
        "markers": [
          "package.json"
        ]
      }
    ],
    "frameworks": [
      {
        "name": "vue",
        "version": "3.2.37",
        "category": "frontend"
      },
      {
        "name": "vite",
        "version": "5.0.0",
        "category": "build"
      }
    ],
    "packageManager": "pnpm",
    "runtime": null
  },
  "build": {
    "buildCommand": "pnpm build",
    "testCommand": null,
    "lintCommand": "pnpm lint",
    "devCommand": null,
    "scripts": {
      "serve": "vite",
      "build": "vite build",
      "preview": "vite preview",
      "lint": "eslint --ext .js,.vue src"
    }
  },
  "conventions": {
    "namingStyle": null,
    "importStyle": null,
    "testPattern": null,
    "fileOrganization": "type-based"
  },
  "structure": {
    "isMonorepo": false,
    "workspaces": [],
    "mainDirectories": [
      "public",
      "src",
      "tests"
    ],
    "gitBranches": {
      "defaultBranch": "master",
      "branchingStrategy": null
    }
  },
  "customNotes": [],
  "directoryMap": {
    "config": {
      "path": "config",
      "purpose": "Configuration files",
      "fileCount": 1,
      "lastAccessed": 1776214627557,
      "keyFiles": [
        "buttons.js"
      ]
    },
    "dist": {
      "path": "dist",
      "purpose": "Distribution/build output",
      "fileCount": 3,
      "lastAccessed": 1776214627558,
      "keyFiles": [
        "index.html",
        "wcslogo.png",
        "wms_d.png"
      ]
    },
    "public": {
      "path": "public",
      "purpose": "Public files",
      "fileCount": 3,
      "lastAccessed": 1776214627572,
      "keyFiles": [
        "index.html",
        "wcslogo.png",
        "wms_d.png"
      ]
    },
    "src": {
      "path": "src",
      "purpose": "Source code",
      "fileCount": 2,
      "lastAccessed": 1776214627573,
      "keyFiles": [
        "App.vue",
        "main.js"
      ]
    },
    "tests": {
      "path": "tests",
      "purpose": "Test files",
      "fileCount": 0,
      "lastAccessed": 1776214627573,
      "keyFiles": []
    },
    "dist\\assets": {
      "path": "dist\\assets",
      "purpose": "Static assets",
      "fileCount": 87,
      "lastAccessed": 1776214627574,
      "keyFiles": [
        "401-BfTrT_7C.js",
        "404-CUk7f22q.js",
        "Audit-C52MvHzW.css"
      ]
    },
    "dist\\static": {
      "path": "dist\\static",
      "purpose": "Static files",
      "fileCount": 1,
      "lastAccessed": 1776214627575,
      "keyFiles": [
        "login_bg.png"
      ]
    },
    "public\\static": {
      "path": "public\\static",
      "purpose": "Static files",
      "fileCount": 1,
      "lastAccessed": 1776214627575,
      "keyFiles": [
        "login_bg.png"
      ]
    },
    "src\\api": {
      "path": "src\\api",
      "purpose": "API routes",
      "fileCount": 3,
      "lastAccessed": 1776214627576,
      "keyFiles": [
        "http.js",
        "permission.js",
        "useTest.js"
      ]
    },
    "src\\assets": {
      "path": "src\\assets",
      "purpose": "Static assets",
      "fileCount": 1,
      "lastAccessed": 1776214627577,
      "keyFiles": [
        "logo.png"
      ]
    },
    "src\\components": {
      "path": "src\\components",
      "purpose": "UI components",
      "fileCount": 0,
      "lastAccessed": 1776214627577,
      "keyFiles": []
    },
    "src\\views": {
      "path": "src\\views",
      "purpose": "View templates",
      "fileCount": 4,
      "lastAccessed": 1776214627577,
      "keyFiles": [
        "fix.js",
        "Home.vue",
        "Index.vue"
      ]
    }
  },
  "hotPaths": [],
  "userDirectives": []
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IInboundTaskFlowService.cs
@@ -15,7 +15,7 @@
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS任务原始数据。</param>
        void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source);
        WebResponseContent InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source);
        /// <summary>
        /// æŽ¨è¿›å…¥åº“任务到下一状态。
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IOutboundTaskFlowService.cs
@@ -15,7 +15,7 @@
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS任务原始数据。</param>
        void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source);
        WebResponseContent InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source);
        /// <summary>
        /// æŽ¨è¿›å‡ºåº“任务到下一状态。
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRelocationTaskFlowService.cs
@@ -15,7 +15,7 @@
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS任务原始数据。</param>
        void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source);
        WebResponseContent InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source);
        /// <summary>
        /// æŽ¨è¿›ç§»åº“任务到下一状态。
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotTaskFlowService.cs
@@ -15,7 +15,7 @@
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS任务原始数据。</param>
        void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source);
        WebResponseContent InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source);
        /// <summary>
        /// æŽ¨è¿›æœºæ¢°æ‰‹ä»»åŠ¡åˆ°ä¸‹ä¸€çŠ¶æ€ã€‚
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/InboundTaskFlowService.cs
@@ -38,17 +38,20 @@
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS任务原始数据。</param>
        public void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source)
        public WebResponseContent InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source)
        {
            WebResponseContent content = new WebResponseContent();
            Dt_Router routers = _routerService.QueryNextRoute(source.SourceAddress);
            if (routers.IsNullOrEmpty())
            {
                return;
                return content.Error("未找到路由信息");
            }
            task.TaskStatus = (int)TaskInStatusEnum.InNew;
            task.CurrentAddress = source.SourceAddress;
            task.NextAddress = routers.ChildPosi;
            return content.OK();
        }
        /// <summary>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs
@@ -56,18 +56,20 @@
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS任务原始数据。</param>
        public void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source)
        public WebResponseContent InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source)
        {
            WebResponseContent content = new WebResponseContent();
            int taskType = task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty ? 100 : task.TaskType;
            Dt_Router router = _routerService.QueryNextRoute(source.Roadway, source.TargetAddress, taskType);
            if (router == null)
            {
                return;
                return content.Error("未找到设备路由信息");
            }
            task.TaskStatus = (int)TaskOutStatusEnum.OutNew;
            task.CurrentAddress = source.SourceAddress;
            task.NextAddress = router.ChildPosi;
            return content.OK();
        }
        /// <summary>
@@ -135,15 +137,25 @@
            task.Modifier = "System";
            // é€šçŸ¥WMS出库完成并获取返回结果
            return  NotifyWMSOutboundFinish(task);
        }
        /// <summary>
        /// é€šçŸ¥WMS出库完成。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>通知结果。</returns>
        private WebResponseContent NotifyWMSOutboundFinish(Dt_Task task)
        {
            WebResponseContent content = new WebResponseContent();
            // é€šçŸ¥WMS出库完成并获取返回结果
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.OutboundFinishTaskAsync),
                new StockInfoDTO { PalletCode = task.PalletCode, TaskNum = task.TaskNum }.ToJson());
            if (!result.IsSuccess || !result.Data.Status)
            {
                return content.Error($"通知WMS系统堆垛机出库完成失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】");
            }
            // å¤„理WMS返回的入库任务(如果有)
            if (result.Data?.Data != null)
            {
@@ -171,25 +183,7 @@
                    });
                }
            }
            return content.OK($"通知WMS系统堆垛机出库完成成功,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】");
        }
        /// <summary>
        /// é€šçŸ¥WMS出库完成。
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <returns>通知结果。</returns>
        private WebResponseContent NotifyWMSOutboundFinish(Dt_Task task)
        {
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.OutboundFinishTaskAsync),
                new StockInfoDTO { PalletCode = task.PalletCode, TaskNum = task.TaskNum }.ToJson());
            if (!result.IsSuccess || !result.Data.Status)
                return WebResponseContent.Instance.Error($"通知WMS系统堆垛机出库完成失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】");
            return WebResponseContent.Instance.OK();
        }
        /// <summary>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/RelocationTaskFlowService.cs
@@ -34,9 +34,10 @@
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS任务原始数据。</param>
        public void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source)
        public WebResponseContent InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source)
        {
            // å½“前版本移库任务接收时不需要额外设置路由或状态。
            return WebResponseContent.Instance.OK();
        }
        /// <summary>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/RobotTaskFlowService.cs
@@ -19,9 +19,10 @@
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS任务原始数据。</param>
        public void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source)
        public WebResponseContent InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source)
        {
            // å½“前版本机械手任务接收时不需要额外设置路由或状态。
            return WebResponseContent.Instance.OK();
        }
        /// <summary>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs
@@ -112,7 +112,9 @@
                    }
                    Dt_Task task = _mapper.Map<Dt_Task>(item);
                    task.Creater = "WMS";
                    InitializeTaskOnReceive(task, item);
                    content = InitializeTaskOnReceive(task, item);
                    if (!content.Status)
                        return content;
                    tasks.Add(task);
                }
                // TOOD: è¿™é‡Œæ³¨æ„æ·»åŠ é”™è¯¯è¦è¿”å›žé”™è¯¯
@@ -170,24 +172,20 @@
        /// </summary>
        /// <param name="task">任务实体。</param>
        /// <param name="source">WMS原始任务对象。</param>
        private void InitializeTaskOnReceive(Dt_Task task, WMSTaskDTO source)
        private WebResponseContent InitializeTaskOnReceive(Dt_Task task, WMSTaskDTO source)
        {
            switch (task.TaskType.GetTaskTypeGroup())
            {
                case TaskTypeGroup.OutbondGroup:
                    _outboundTaskFlowService.InitializeOnReceive(task, source);
                    break;
                    return _outboundTaskFlowService.InitializeOnReceive(task, source);
                case TaskTypeGroup.InboundGroup:
                    _inboundTaskFlowService.InitializeOnReceive(task, source);
                    break;
                    return _inboundTaskFlowService.InitializeOnReceive(task, source);
                case TaskTypeGroup.RelocationGroup:
                    _relocationTaskFlowService.InitializeOnReceive(task, source);
                    break;
                    return _relocationTaskFlowService.InitializeOnReceive(task, source);
                case TaskTypeGroup.OtherGroup:
                    _robotTaskFlowService.InitializeOnReceive(task, source);
                    break;
                    return _robotTaskFlowService.InitializeOnReceive(task, source);
                default:
                    break;
                    return WebResponseContent.Instance.Error("WCS不存在当前任务的任务类型");
            }
        }
@@ -398,7 +396,9 @@
                && result.Data is List<WMSTaskDTO> wmsTasks
                && wmsTasks.Count > 0)
            {
                return ReceiveWMSTask(wmsTasks);
                WebResponseContent content = ReceiveWMSTask(wmsTasks);
                if (!content.Status)
                    return content;
            }
            // æ›´æ–°ä»»åŠ¡æ•°æ®
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/CommonConveyorLineNewJob.cs
@@ -133,8 +133,7 @@
                    if (childDeviceCodes == null || childDeviceCodes.Count == 0)
                    {
                        // æ²¡æœ‰å­è®¾å¤‡ï¼Œç›´æŽ¥è¿”回
                        _logger.LogInformation("输送线 {DeviceCode} æ²¡æœ‰å­è®¾å¤‡", conveyorLine.DeviceCode);
                        QuartzLogger.Info($"输送线 {conveyorLine.DeviceCode} æ²¡æœ‰å­è®¾å¤‡", conveyorLine.DeviceCode);
                        QuartzLogHelper.LogInfo(_logger, "输送线 {DeviceCode} æ²¡æœ‰å­è®¾å¤‡", $"输送线 {conveyorLine.DeviceCode} æ²¡æœ‰å­è®¾å¤‡", conveyorLine.DeviceCode, conveyorLine.DeviceCode);
                        return Task.CompletedTask;
                    }
@@ -162,8 +161,6 @@
                            // å¦‚果命令为空,跳过
                            if (command == null)
                            {
                                _logger.LogDebug("Execute:子设备 {ChildDeviceCode} å‘½ä»¤ä¸ºç©ºï¼Œè·³è¿‡", childDeviceCode);
                                QuartzLogger.Debug($"子设备 {childDeviceCode} å‘½ä»¤ä¸ºç©ºï¼Œè·³è¿‡", conveyorLine.DeviceCode);
                                continue;
                            }
@@ -186,8 +183,7 @@
                                    {
                                        // æ²¡æœ‰ä»»åŠ¡ï¼Œå‘ WMS è¯·æ±‚出库托盘任务
                                        var position = checkPalletPositions.FirstOrDefault(x => x.Code == childDeviceCode);
                                        _logger.LogInformation("Execute:检查托盘位置 {ChildDeviceCode},请求WMS出库托盘任务", childDeviceCode);
                                        QuartzLogger.Info($"检查托盘位置 {childDeviceCode},请求WMS出库托盘任务", conveyorLine.DeviceCode);
                                        QuartzLogHelper.LogInfo(_logger, "Execute:检查托盘位置 {ChildDeviceCode},请求WMS出库托盘任务", $"检查托盘位置 {childDeviceCode},请求WMS出库托盘任务", conveyorLine.DeviceCode, childDeviceCode);
                                        var responseResult = _httpClientHelper.Post<WebResponseContent>("GetOutBoundTrayTaskAsync", new CreateTaskDto()
                                        {
@@ -229,8 +225,7 @@
                                }
                                catch (Exception ex)
                                {
                                    _logger.LogError(ex, "处理手动入库任务异常");
                                    QuartzLogger.Error($"处理手动入库任务异常: {ex.Message}", "CommonConveyorLineNewJob", ex);
                                    QuartzLogHelper.LogError(_logger, ex, "处理手动入库任务异常", $"处理手动入库任务异常: {ex.Message}", "CommonConveyorLineNewJob");
                                }
                                continue;
                            }
@@ -239,8 +234,6 @@
                            // æ— æ‰˜ç›˜æ¡ç æ—¶ï¼Œè¯·æ±‚出库任务
                            if (command.Barcode.IsNullOrEmpty() || command.Barcode.Replace("\0", "") == "")
                            {
                                _logger.LogDebug("Execute:子设备 {ChildDeviceCode} æ— æ‰˜ç›˜æ¡ç ï¼Œè¯·æ±‚出库任务", childDeviceCode);
                                QuartzLogger.Debug($"子设备 {childDeviceCode} æ— æ‰˜ç›˜æ¡ç ï¼Œè¯·æ±‚出库任务", conveyorLine.DeviceCode);
                                _conveyorLineDispatch.RequestOutbound(conveyorLine, command, childDeviceCode);
                                continue;
                            }
@@ -252,8 +245,7 @@
                                Dt_Task task = _taskService.QueryExecutingConveyorLineTask(command.TaskNo, childDeviceCode);
                                if (!task.IsNullOrEmpty())
                                {
                                    _logger.LogInformation("Execute:子设备 {ChildDeviceCode} å¤„理任务 {TaskNum},状态: {Status}", childDeviceCode, task.TaskNum, task.TaskStatus);
                                    QuartzLogger.Info($"处理任务 {task.TaskNum},状态: {task.TaskStatus}", conveyorLine.DeviceCode);
                                    QuartzLogHelper.LogInfo(_logger, "Execute:子设备 {ChildDeviceCode} å¤„理任务 {TaskNum},状态: {Status}", $"处理任务 {task.TaskNum},状态: {task.TaskStatus}", conveyorLine.DeviceCode, childDeviceCode, task.TaskNum, task.TaskStatus);
                                    // å¤„理任务状态(根据状态分发到不同方法)
                                    ProcessTaskState(conveyorLine, command, task, childDeviceCode);
                                    return Task.CompletedTask;
@@ -263,8 +255,7 @@
                        catch (Exception innerEx)
                        {
                            // è®°å½•异常,但不影响其他子设备的处理
                            _logger.LogError(innerEx, "Execute:子设备 {ChildDeviceCode} å¤„理异常,CorrelationId: {CorrelationId}", childDeviceCode, correlationId);
                            QuartzLogger.Error($"子设备处理异常: {innerEx.Message}", conveyorLine.DeviceCode, innerEx);
                            QuartzLogHelper.LogError(_logger, innerEx, "Execute:子设备 {ChildDeviceCode} å¤„理异常,CorrelationId: {CorrelationId}", $"子设备处理异常: {innerEx.Message}", conveyorLine.DeviceCode, childDeviceCode, correlationId);
                        }
                    }
                }
@@ -272,8 +263,7 @@
            catch (Exception ex)
            {
                // è®°å½•整体异常
                _logger.LogError(ex, "Execute:输送线 {DeviceCode} æ‰§è¡Œå¼‚常", ex.Message);
                QuartzLogger.Error($"输送线执行异常: {ex.Message}", "CommonConveyorLineNewJob", ex);
                QuartzLogHelper.LogError(_logger, ex, "Execute:输送线 {DeviceCode} æ‰§è¡Œå¼‚常", $"输送线执行异常: {ex.Message}", "CommonConveyorLineNewJob", ex.Message);
            }
            return Task.CompletedTask;
        }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs
@@ -105,8 +105,7 @@
        {
            // æ¸…除任务号,表示当前空闲
            conveyorLine.SetValue(ConveyorLineDBNameNew.TaskNo, 0, childDeviceCode);
            _logger.LogDebug("HeartBeat:子设备 {ChildDeviceCode} å¿ƒè·³", childDeviceCode);
            QuartzLogger.Debug($"HeartBeat:子设备 {childDeviceCode} å¿ƒè·³", conveyorLine.DeviceCode);
            QuartzLogHelper.LogDebug(_logger, "HeartBeat:子设备 {ChildDeviceCode} å¿ƒè·³", $"HeartBeat:子设备 {childDeviceCode} å¿ƒè·³", conveyorLine.DeviceCode, childDeviceCode);
        }
        /// <summary>
@@ -125,8 +124,7 @@
        /// <param name="childDeviceCode">子设备编码</param>
        public void RequestInbound(CommonConveyorLine conveyorLine, ConveyorLineTaskCommandNew command, string childDeviceCode)
        {
            _logger.LogInformation("RequestInbound:子设备 {ChildDeviceCode} è¯·æ±‚入库", childDeviceCode);
            QuartzLogger.Info($"请求入库,子设备: {childDeviceCode}", conveyorLine.DeviceCode);
            QuartzLogHelper.LogInfo(_logger, "RequestInbound:子设备 {ChildDeviceCode} è¯·æ±‚入库", $"请求入库,子设备: {childDeviceCode}", conveyorLine.DeviceCode, childDeviceCode);
            // å‘ WMS è¯·æ±‚新任务(基于条码)
            if (_taskFilter.RequestWmsTask(command.Barcode, childDeviceCode))
@@ -147,8 +145,7 @@
                    // æ›´æ–°ä»»åŠ¡çŠ¶æ€åˆ°ä¸‹ä¸€é˜¶æ®µ
                    _taskService.UpdateTaskStatusToNext(task);
                    _logger.LogInformation("RequestInbound:入库任务已下发,任务号: {TaskNum},子设备: {ChildDeviceCode}", task.TaskNum, childDeviceCode);
                    QuartzLogger.Info($"入库任务已下发,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode);
                    QuartzLogHelper.LogInfo(_logger, "RequestInbound:入库任务已下发,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"入库任务已下发,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode);
                }
            }
        }
@@ -169,13 +166,11 @@
            Dt_Task? task = _taskFilter.QueryExecutingTask(command.TaskNo, childDeviceCode);
            if (task == null)
            {
                _logger.LogDebug("RequestInNextAddress:任务 {TaskNo} ä¸å­˜åœ¨", command.TaskNo);
                QuartzLogger.Debug($"RequestInNextAddress:任务 {command.TaskNo} ä¸å­˜åœ¨", conveyorLine.DeviceCode);
                QuartzLogHelper.LogDebug(_logger, "RequestInNextAddress:任务 {TaskNo} ä¸å­˜åœ¨", $"RequestInNextAddress:任务 {command.TaskNo} ä¸å­˜åœ¨", conveyorLine.DeviceCode, command.TaskNo);
                return;
            }
            _logger.LogInformation("RequestInNextAddress:入库下一地址,任务号: {TaskNum},子设备: {ChildDeviceCode}", task.TaskNum, childDeviceCode);
            QuartzLogger.Info($"RequestInNextAddress:入库下一地址,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode);
            QuartzLogHelper.LogInfo(_logger, "RequestInNextAddress:入库下一地址,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"RequestInNextAddress:入库下一地址,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode);
            // å¦‚果不是空托盘任务,处理目标地址(与拘束机/插拔钉机交互)
            if (task.TaskType != (int)TaskOutboundTypeEnum.OutEmpty)
@@ -212,8 +207,7 @@
                {
                    // å›žå¤ ACK ç¡®è®¤
                    conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
                    _logger.LogInformation("ConveyorLineInFinish:入库完成,任务号: {TaskNum},子设备: {ChildDeviceCode}", task.TaskNum, childDeviceCode);
                    QuartzLogger.Info($"入库完成,任务号: {task.TaskNum}", conveyorLine.DeviceCode);
                    QuartzLogHelper.LogInfo(_logger, "ConveyorLineInFinish:入库完成,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"入库完成,任务号: {task.TaskNum}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode);
                }
@@ -254,8 +248,7 @@
                // æ›´æ–°ä»»åŠ¡çŠ¶æ€
                _taskService.UpdateTaskStatusToNext(task);
                _logger.LogInformation("RequestOutbound:出库任务已下发,任务号: {TaskNum},子设备: {ChildDeviceCode}", task.TaskNum, childDeviceCode);
                QuartzLogger.Info($"出库任务已下发,任务号: {task.TaskNum}", conveyorLine.DeviceCode);
                QuartzLogHelper.LogInfo(_logger, "RequestOutbound:出库任务已下发,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"出库任务已下发,任务号: {task.TaskNum}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode);
            }
        }
@@ -275,13 +268,11 @@
            Dt_Task? task = _taskFilter.QueryExecutingTask(command.TaskNo, childDeviceCode);
            if (task == null)
            {
                _logger.LogDebug("RequestOutNextAddress:任务 {TaskNo} ä¸å­˜åœ¨", command.TaskNo);
                QuartzLogger.Debug($"RequestOutNextAddress:任务 {command.TaskNo} ä¸å­˜åœ¨", conveyorLine.DeviceCode);
                QuartzLogHelper.LogDebug(_logger, "RequestOutNextAddress:任务 {TaskNo} ä¸å­˜åœ¨", $"RequestOutNextAddress:任务 {command.TaskNo} ä¸å­˜åœ¨", conveyorLine.DeviceCode, command.TaskNo);
                return;
            }
            _logger.LogInformation("RequestOutNextAddress:出库下一地址,任务号: {TaskNum},子设备: {ChildDeviceCode}", task.TaskNum, childDeviceCode);
            QuartzLogger.Info($"RequestOutNextAddress:出库下一地址,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode);
            QuartzLogHelper.LogInfo(_logger, "RequestOutNextAddress:出库下一地址,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"RequestOutNextAddress:出库下一地址,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode);
            // å¦‚果不是空托盘任务,处理目标地址
            if (task.TaskType != (int)TaskOutboundTypeEnum.OutEmpty)
@@ -315,11 +306,13 @@
                // æ›´æ–°ä»»åŠ¡çŠ¶æ€åˆ°ä¸‹ä¸€é˜¶æ®µï¼ˆé€šå¸¸æ˜¯å®Œæˆï¼‰
                WebResponseContent content = _taskService.UpdateTaskStatusToNext(task);
                if (content.Status)
                {
                // å›žå¤ ACK ç¡®è®¤
                conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
                }
                _logger.LogInformation("ConveyorLineOutFinish:出库完成,任务号: {TaskNum},子设备: {ChildDeviceCode}", task.TaskNum, childDeviceCode);
                QuartzLogger.Info($"出库完成,任务号: {task.TaskNum}", conveyorLine.DeviceCode);
                QuartzLogHelper.LogInfo(_logger, "ConveyorLineOutFinish:出库完成,完成结果:{Status},任务号: {TaskNum},子设备: {ChildDeviceCode},错误消息: {Message}", $"出库完成,完成结果:{content.Status},任务号: {task.TaskNum},错误消息:{content.Message}", conveyorLine.DeviceCode, content.Status, task.TaskNum, childDeviceCode, content.Message);
            }
        }
    }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs
@@ -418,10 +418,7 @@
            string deviceType)
        {
            // è®°å½•当前请求状态的调试日志,供排查问题使用
            _logger.LogDebug("ProcessDeviceRequest:{DeviceType},子设备: {ChildDeviceCode},物料请求: {MaterialReq},出料请求: {OutputReq}",
                deviceType, childDeviceCode, materialRequest, outputRequest);
            // åŒæ­¥å†™å…¥ Quartz æ—¥å¿—文件(双写可追溯,这里保留与原逻辑一致的行为)
            QuartzLogger.Debug($"ProcessDeviceRequest:{deviceType},子设备: {childDeviceCode},物料请求: {materialRequest},出料请求: {outputRequest}", conveyorLine.DeviceCode);
            QuartzLogHelper.LogDebug(_logger, "ProcessDeviceRequest:{DeviceType},子设备: {ChildDeviceCode},物料请求: {MaterialReq},出料请求: {OutputReq}", $"ProcessDeviceRequest:{deviceType},子设备: {childDeviceCode},物料请求: {materialRequest},出料请求: {outputRequest}", conveyorLine.DeviceCode, deviceType, childDeviceCode, materialRequest, outputRequest);
            // åˆ†æ”¯åˆ¤æ–­ï¼šè®¾å¤‡æ˜¯éœ€è¦ç‰©æ–™è¿˜æ˜¯éœ€è¦å‡ºæ–™
            if (materialRequest)
@@ -432,8 +429,7 @@
                // 2. å›žå¤ ACK ç¡®è®¤ä¿¡å·ï¼Œå‘ŠçŸ¥è®¾å¤‡å·²æ”¶åˆ°è¯·æ±‚
                conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, 1, childDeviceCode);
                // 3. è®°å½•信息日志,表明已完成目标地址设置和 ACK å›žå¤
                _logger.LogInformation("ProcessDeviceRequest:{DeviceType} éœ€è¦ç‰©æ–™ï¼Œå·²è®¾ç½®ç›®æ ‡åœ°å€å’ŒACK", deviceType);
                QuartzLogger.Info($"ProcessDeviceRequest:{deviceType} éœ€è¦ç‰©æ–™ï¼Œå·²è®¾ç½®ç›®æ ‡åœ°å€å’ŒACK", conveyorLine.DeviceCode);
                QuartzLogHelper.LogInfo(_logger, "ProcessDeviceRequest:{DeviceType} éœ€è¦ç‰©æ–™ï¼Œå·²è®¾ç½®ç›®æ ‡åœ°å€å’ŒACK", $"ProcessDeviceRequest:{deviceType} éœ€è¦ç‰©æ–™ï¼Œå·²è®¾ç½®ç›®æ ‡åœ°å€å’ŒACK", conveyorLine.DeviceCode, deviceType);
            }
            else
            {
@@ -457,10 +453,7 @@
        private void WriteDebug(CommonConveyorLine conveyorLine, string scenario, string childDeviceCode, string nextAddress)
        {
            // å†™å…¥ç»“构化日志(可被 Serilog ç­‰æ—¥å¿—框架捕获)
            _logger.LogDebug("Handle{Scenario}:子设备: {ChildDeviceCode},目标地址: {NextAddress}",
                scenario, childDeviceCode, nextAddress);
            // å†™å…¥ Quartz ä¸“用日志文件(供定时任务轨迹追踪)
            QuartzLogger.Debug($"Handle{scenario}:子设备: {childDeviceCode},目标地址: {nextAddress}", conveyorLine.DeviceCode);
            QuartzLogHelper.LogDebug(_logger, "Handle{Scenario}:子设备: {ChildDeviceCode},目标地址: {NextAddress}", $"Handle{scenario}:子设备: {childDeviceCode},目标地址: {nextAddress}", conveyorLine.DeviceCode, scenario, childDeviceCode, nextAddress);
        }
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTaskFilter.cs
@@ -56,8 +56,7 @@
        public Dt_Task? QueryPendingTask(string deviceCode, string childDeviceCode)
        {
            var task = _taskService.QueryConveyorLineTask(deviceCode, childDeviceCode);
            _logger.LogDebug("QueryPendingTask:设备 {DeviceCode},子设备 {ChildDeviceCode},查询结果: {TaskNum}", deviceCode, childDeviceCode, task?.TaskNum);
            QuartzLogger.Debug($"QueryPendingTask:设备 {deviceCode},子设备 {childDeviceCode},查询结果: {task?.TaskNum}", deviceCode);
            QuartzLogHelper.LogDebug(_logger, "QueryPendingTask:设备 {DeviceCode},子设备 {ChildDeviceCode},查询结果: {TaskNum}", $"QueryPendingTask:设备 {deviceCode},子设备 {childDeviceCode},查询结果: {task?.TaskNum}", deviceCode, deviceCode, childDeviceCode, task?.TaskNum);
            return task;
        }
@@ -74,8 +73,7 @@
        public Dt_Task? QueryExecutingTask(int taskNo, string childDeviceCode)
        {
            var task = _taskService.QueryExecutingConveyorLineTask(taskNo, childDeviceCode);
            _logger.LogDebug("QueryExecutingTask:任务号 {TaskNo},子设备 {ChildDeviceCode},查询结果: {Found}", taskNo, childDeviceCode, task != null);
            QuartzLogger.Debug($"QueryExecutingTask:任务号 {taskNo},子设备 {childDeviceCode},查询结果: {(task != null)}", childDeviceCode);
            QuartzLogHelper.LogDebug(_logger, "QueryExecutingTask:任务号 {TaskNo},子设备 {ChildDeviceCode},查询结果: {Found}", $"QueryExecutingTask:任务号 {taskNo},子设备 {childDeviceCode},查询结果: {(task != null)}", childDeviceCode, taskNo, childDeviceCode, task != null);
            return task;
        }
@@ -91,8 +89,7 @@
        /// <returns>请求是否成功</returns>
        public bool RequestWmsTask(string barcode, string childDeviceCode)
        {
            _logger.LogInformation("RequestWmsTask:向WMS请求任务,条码: {Barcode},子设备: {ChildDeviceCode}", barcode, childDeviceCode);
            QuartzLogger.Info($"向WMS请求任务,条码: {barcode}", childDeviceCode);
            QuartzLogHelper.LogInfo(_logger, "RequestWmsTask:向WMS请求任务,条码: {Barcode},子设备: {ChildDeviceCode}", $"向WMS请求任务,条码: {barcode}", childDeviceCode, barcode, childDeviceCode);
            var result = _taskService.RequestWMSTask(barcode, childDeviceCode);
            return result.Status;
        }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/QuartzLogHelper.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,85 @@
using Microsoft.Extensions.Logging;
using WIDESEAWCS_Core.LogHelper;
namespace WIDESEAWCS_Tasks;
/// <summary>
/// Quartz ä½œä¸šæ—¥å¿—帮助类 - ç»Ÿä¸€å°è£… ILogger å’Œ QuartzLogger çš„双通道日志记录
/// </summary>
/// <remarks>
/// æ‰€æœ‰ Quartz Job ä¸­éœ€è¦åŒæ—¶å†™å…¥ ILogger(Serilog)和 QuartzLogger(文件日志)的场景,
/// ç»Ÿä¸€è°ƒç”¨æ­¤å¸®åŠ©ç±»çš„æ–¹æ³•ï¼Œé¿å…é‡å¤ç¼–å†™ä¸¤è¡Œæ—¥å¿—ä»£ç ã€‚
/// </remarks>
public static class QuartzLogHelper
{
    /// <summary>
    /// è®°å½•错误日志(带异常对象)
    /// </summary>
    /// <param name="logger">ILogger å®žä¾‹</param>
    /// <param name="ex">异常对象</param>
    /// <param name="loggerMessage">ILogger çš„结构化日志模板(支持占位符)</param>
    /// <param name="quartzMessage">QuartzLogger çš„æ—¥å¿—消息</param>
    /// <param name="deviceCode">设备编码</param>
    /// <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);
        QuartzLogger.Error(quartzMessage, deviceCode, ex);
    }
    /// <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 LogError(ILogger logger, string loggerMessage, string quartzMessage, string deviceCode, params object[] args)
    {
        logger.LogError(loggerMessage, args);
        QuartzLogger.Error(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 LogInfo(ILogger logger, string loggerMessage, string quartzMessage, string deviceCode, params object[] args)
    {
        logger.LogInformation(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>
    /// <param name="args">ILogger ç»“构化日志的参数</param>
    public static void LogWarn(ILogger logger, string loggerMessage, string quartzMessage, string deviceCode, params object[] args)
    {
        logger.LogWarning(loggerMessage, args);
        QuartzLogger.Warn(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 quartzMessage, string deviceCode, params object[] args)
    {
        logger.LogDebug(loggerMessage, args);
        QuartzLogger.Debug(quartzMessage, deviceCode);
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/CommonStackerCraneJob.cs
@@ -174,8 +174,7 @@
                if (!flag || value is not CommonStackerCrane commonStackerCrane)
                {
                    // å‚数无效,直接返回
                    _logger.LogWarning("Execute:参数无效");
                    QuartzLogger.Warn("Execute:参数无效", "CommonStackerCraneJob");
                    QuartzLogHelper.LogWarn(_logger, "Execute:参数无效", "Execute:参数无效", "CommonStackerCraneJob");
                    return Task.CompletedTask;
                }
@@ -186,8 +185,7 @@
                {
                    // ç»‘定任务完成事件处理方法
                    commonStackerCrane.StackerCraneTaskCompletedEventHandler += CommonStackerCrane_StackerCraneTaskCompletedEventHandler;
                    _logger.LogInformation("Execute:订阅任务完成事件,设备: {DeviceCode}", _deviceCode);
                    QuartzLogger.Info($"订阅任务完成事件", _deviceCode);
                    QuartzLogHelper.LogInfo(_logger, "Execute:订阅任务完成事件,设备: {DeviceCode}", "订阅任务完成事件", _deviceCode, _deviceCode);
                }
                // ========== æ£€æŸ¥å †åž›æœºä»»åŠ¡å®ŒæˆçŠ¶æ€ ==========
@@ -225,8 +223,7 @@
                if (stackerCraneTaskCommand == null)
                {
                    // å‘½ä»¤æž„建失败
                    _logger.LogWarning("Execute:命令构建失败,设备: {DeviceCode},任务号: {TaskNum}", _deviceCode, task.TaskNum);
                    QuartzLogger.Warn($"命令构建失败,任务号: {task.TaskNum}", _deviceCode);
                    QuartzLogHelper.LogWarn(_logger, "Execute:命令构建失败,设备: {DeviceCode},任务号: {TaskNum}", $"命令构建失败,任务号: {task.TaskNum}", _deviceCode, _deviceCode, task.TaskNum);
                    return Task.CompletedTask;
                }
@@ -240,20 +237,17 @@
                    commonStackerCrane.LastTaskType = task.TaskType;
                    _taskService.UpdateTaskStatusToNext(task.TaskNum);
                    _logger.LogInformation("Execute:命令发送成功,设备: {DeviceCode},任务号: {TaskNum}", _deviceCode, task.TaskNum);
                    QuartzLogger.Info($"命令发送成功,任务号: {task.TaskNum}", _deviceCode);
                    QuartzLogHelper.LogInfo(_logger, "Execute:命令发送成功,设备: {DeviceCode},任务号: {TaskNum}", $"命令发送成功,任务号: {task.TaskNum}", _deviceCode, _deviceCode, task.TaskNum);
                }
                else
                {
                    _logger.LogError("Execute:命令发送失败,设备: {DeviceCode},任务号: {TaskNum}", _deviceCode, task.TaskNum);
                    QuartzLogger.Error($"命令发送失败", _deviceCode);
                    QuartzLogHelper.LogError(_logger, "Execute:命令发送失败,设备: {DeviceCode},任务号: {TaskNum}", $"命令发送失败", _deviceCode, _deviceCode, task.TaskNum);
                }
            }
            catch (Exception ex)
            {
                // è®°å½•异常
                _logger.LogError(ex, "Execute:执行异常,设备: {DeviceCode}", _deviceCode);
                QuartzLogger.Error($"执行异常: {ex.Message}", _deviceCode, ex);
                QuartzLogHelper.LogError(_logger, ex, "Execute:执行异常,设备: {DeviceCode}", $"执行异常: {ex.Message}", _deviceCode, _deviceCode);
            }
            return Task.CompletedTask;
@@ -277,8 +271,7 @@
            if (stackerCrane != null)
            {
                // è®°å½•日志
                _logger.LogInformation("CommonStackerCrane_StackerCraneTaskCompletedEventHandler:任务完成,任务号: {TaskNum}", e.TaskNum);
                QuartzLogger.Info($"任务完成,任务号: {e.TaskNum}", stackerCrane.DeviceCode);
                QuartzLogHelper.LogInfo(_logger, "CommonStackerCrane_StackerCraneTaskCompletedEventHandler:任务完成,任务号: {TaskNum}", $"任务完成,任务号: {e.TaskNum}", stackerCrane.DeviceCode, e.TaskNum);
                // æ›´æ–°ä»»åŠ¡çŠ¶æ€ä¸ºå®Œæˆ
                if (_taskService.StackCraneTaskCompleted(e.TaskNum).Status)
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneCommandBuilder.cs
@@ -105,14 +105,12 @@
            {
                if (roadway.Contains(mapping.Key))
                {
                    _logger.LogDebug("GetCommandType:匹配巷道 {Roadway},命令类型: {CommandType}", roadway, mapping.Value);
                    QuartzLogger.Debug($"GetCommandType:匹配巷道 {roadway},命令类型: {mapping.Value}", roadway);
                    QuartzLogHelper.LogDebug(_logger, "GetCommandType:匹配巷道 {Roadway},命令类型: {CommandType}", $"GetCommandType:匹配巷道 {roadway},命令类型: {mapping.Value}", roadway, roadway, mapping.Value);
                    return mapping.Value;
                }
            }
            _logger.LogDebug("GetCommandType:巷道 {Roadway} æœªåŒ¹é…ï¼Œä½¿ç”¨é»˜è®¤å‘½ä»¤ç±»åž‹: {DefaultType}", roadway, _config.DefaultCommandType);
            QuartzLogger.Debug($"GetCommandType:巷道 {roadway} æœªåŒ¹é…ï¼Œä½¿ç”¨é»˜è®¤å‘½ä»¤ç±»åž‹: {_config.DefaultCommandType}", roadway);
            QuartzLogHelper.LogDebug(_logger, "GetCommandType:巷道 {Roadway} æœªåŒ¹é…ï¼Œä½¿ç”¨é»˜è®¤å‘½ä»¤ç±»åž‹: {DefaultType}", $"GetCommandType:巷道 {roadway} æœªåŒ¹é…ï¼Œä½¿ç”¨é»˜è®¤å‘½ä»¤ç±»åž‹: {_config.DefaultCommandType}", roadway, roadway, _config.DefaultCommandType);
            return _config.DefaultCommandType;
        }
@@ -172,8 +170,7 @@
            // èŽ·å–ä»»åŠ¡ç±»åž‹åˆ†ç»„
            TaskTypeGroup taskTypeGroup = task.TaskType.GetTaskTypeGroup();
            _logger.LogDebug("BuildCommand:任务号: {TaskNum},任务类型分组: {TaskTypeGroup}", task.TaskNum, taskTypeGroup);
            QuartzLogger.Debug($"BuildCommand:任务号: {task.TaskNum},任务类型分组: {taskTypeGroup}", task.Roadway);
            QuartzLogHelper.LogDebug(_logger, "BuildCommand:任务号: {TaskNum},任务类型分组: {TaskTypeGroup}", $"BuildCommand:任务号: {task.TaskNum},任务类型分组: {taskTypeGroup}", task.Roadway, task.TaskNum, taskTypeGroup);
            // æ ¹æ®ä»»åŠ¡ç±»åž‹åˆ†å‘æž„å»º
            return taskTypeGroup switch
@@ -200,8 +197,7 @@
        /// <returns>填充好的命令对象</returns>
        private T? BuildInboundCommand<T>(Dt_Task task, T command) where T : class
        {
            _logger.LogInformation("BuildInboundCommand:构建入库命令,任务号: {TaskNum}", task.TaskNum);
            QuartzLogger.Info($"BuildInboundCommand:构建入库命令,任务号: {task.TaskNum}", task.Roadway);
            QuartzLogHelper.LogInfo(_logger, "BuildInboundCommand:构建入库命令,任务号: {TaskNum}", $"BuildInboundCommand:构建入库命令,任务号: {task.TaskNum}", task.Roadway, task.TaskNum);
            // ç¡®å®šä»»åŠ¡ç±»åž‹ï¼ˆç©ºæ‰˜ç›˜ç”¨ç‰¹æ®Šç±»åž‹ï¼‰
            int taskType = 0;
@@ -217,8 +213,7 @@
            if (router == null)
            {
                // æœªæ‰¾åˆ°ç«™å°ï¼Œæ›´æ–°å¼‚常信息
                _logger.LogError("BuildInboundCommand:未找到站台【{CurrentAddress}】信息,任务号: {TaskNum}", task.CurrentAddress, task.TaskNum);
                QuartzLogger.Error($"BuildInboundCommand:未找到站台【{task.CurrentAddress}】信息", task.Roadway);
                QuartzLogHelper.LogError(_logger, "BuildInboundCommand:未找到站台【{CurrentAddress}】信息,任务号: {TaskNum}", $"BuildInboundCommand:未找到站台【{task.CurrentAddress}】信息", task.Roadway, task.CurrentAddress, task.TaskNum);
                _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.CurrentAddress}】信息,无法获取对应的堆垛机取货站台信息");
                return null;
            }
@@ -231,8 +226,7 @@
            // è§£æžç›®æ ‡åœ°å€ï¼ˆåº“位地址)
            if (!TryParseAddress(task.NextAddress, out short endRow, out short endColumn, out short endLayer))
            {
                _logger.LogError("BuildInboundCommand:入库任务终点地址解析失败,终点: {NextAddress},任务号: {TaskNum}", task.NextAddress, task.TaskNum);
                QuartzLogger.Error($"BuildInboundCommand:入库任务终点地址解析失败,终点: {task.NextAddress}", task.Roadway);
                QuartzLogHelper.LogError(_logger, "BuildInboundCommand:入库任务终点地址解析失败,终点: {NextAddress},任务号: {TaskNum}", $"BuildInboundCommand:入库任务终点地址解析失败,终点: {task.NextAddress}", task.Roadway, task.NextAddress, task.TaskNum);
                _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"入库任务终点错误,终点:【{task.NextAddress}】");
                return null;
            }
@@ -242,9 +236,7 @@
            SetCommandProperty(command, "EndColumn", endColumn);
            SetCommandProperty(command, "EndLayer", endLayer);
            _logger.LogInformation("BuildInboundCommand:入库命令构建成功,起点: {StartRow}-{StartColumn}-{StartLayer},终点: {EndRow}-{EndColumn}-{EndLayer},任务号: {TaskNum}",
                router.SrmRow, router.SrmColumn, router.SrmLayer, endRow, endColumn, endLayer, task.TaskNum);
            QuartzLogger.Info($"BuildInboundCommand:入库命令构建成功,起点: {router.SrmRow}-{router.SrmColumn}-{router.SrmLayer},终点: {endRow}-{endColumn}-{endLayer}", task.Roadway);
            QuartzLogHelper.LogInfo(_logger, "BuildInboundCommand:入库命令构建成功,起点: {StartRow}-{StartColumn}-{StartLayer},终点: {EndRow}-{EndColumn}-{EndLayer},任务号: {TaskNum}", $"BuildInboundCommand:入库命令构建成功,起点: {router.SrmRow}-{router.SrmColumn}-{router.SrmLayer},终点: {endRow}-{endColumn}-{endLayer}", task.Roadway, router.SrmRow, router.SrmColumn, router.SrmLayer, endRow, endColumn, endLayer, task.TaskNum);
            return command;
        }
@@ -264,8 +256,7 @@
        /// <returns>填充好的命令对象</returns>
        private T? BuildOutboundCommand<T>(Dt_Task task, T command) where T : class
        {
            _logger.LogInformation("BuildOutboundCommand:构建出库命令,任务号: {TaskNum}", task.TaskNum);
            QuartzLogger.Info($"BuildOutboundCommand:构建出库命令,任务号: {task.TaskNum}", task.Roadway);
            QuartzLogHelper.LogInfo(_logger, "BuildOutboundCommand:构建出库命令,任务号: {TaskNum}", $"BuildOutboundCommand:构建出库命令,任务号: {task.TaskNum}", task.Roadway, task.TaskNum);
            // ç¡®å®šä»»åŠ¡ç±»åž‹
            int taskType = 0;
@@ -280,8 +271,7 @@
            Dt_Router? router = _routerService.QueryNextRoute(task.Roadway, task.TargetAddress, taskType);
            if (router == null)
            {
                _logger.LogError("BuildOutboundCommand:未找到站台【{TargetAddress}】信息,任务号: {TaskNum}", task.TargetAddress, task.TaskNum);
                QuartzLogger.Error($"BuildOutboundCommand:未找到站台【{task.TargetAddress}】信息", task.Roadway);
                QuartzLogHelper.LogError(_logger, "BuildOutboundCommand:未找到站台【{TargetAddress}】信息,任务号: {TaskNum}", $"BuildOutboundCommand:未找到站台【{task.TargetAddress}】信息", task.Roadway, task.TargetAddress, task.TaskNum);
                _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.TargetAddress}】信息,无法获取对应的堆垛机放货站台信息");
                return null;
            }
@@ -294,8 +284,7 @@
            // è§£æžèµ·å§‹åœ°å€ï¼ˆåº“位地址)
            if (!TryParseAddress(task.CurrentAddress, out short startRow, out short startColumn, out short startLayer))
            {
                _logger.LogError("BuildOutboundCommand:出库任务起点地址解析失败,起点: {CurrentAddress},任务号: {TaskNum}", task.CurrentAddress, task.TaskNum);
                QuartzLogger.Error($"BuildOutboundCommand:出库任务起点地址解析失败,起点: {task.CurrentAddress}", task.Roadway);
                QuartzLogHelper.LogError(_logger, "BuildOutboundCommand:出库任务起点地址解析失败,起点: {CurrentAddress},任务号: {TaskNum}", $"BuildOutboundCommand:出库任务起点地址解析失败,起点: {task.CurrentAddress}", task.Roadway, task.CurrentAddress, task.TaskNum);
                _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"出库任务起点错误,起点:【{task.CurrentAddress}】");
                return null;
            }
@@ -305,9 +294,7 @@
            SetCommandProperty(command, "StartColumn", startColumn);
            SetCommandProperty(command, "StartLayer", startLayer);
            _logger.LogInformation("BuildOutboundCommand:出库命令构建成功,起点: {StartRow}-{StartColumn}-{StartLayer},终点: {EndRow}-{EndColumn}-{EndLayer},任务号: {TaskNum}",
                startRow, startColumn, startLayer, router.SrmRow, router.SrmColumn, router.SrmLayer, task.TaskNum);
            QuartzLogger.Info($"BuildOutboundCommand:出库命令构建成功,起点: {startRow}-{startColumn}-{startLayer},终点: {router.SrmRow}-{router.SrmColumn}-{router.SrmLayer}", task.Roadway);
            QuartzLogHelper.LogInfo(_logger, "BuildOutboundCommand:出库命令构建成功,起点: {StartRow}-{StartColumn}-{StartLayer},终点: {EndRow}-{EndColumn}-{EndLayer},任务号: {TaskNum}", $"BuildOutboundCommand:出库命令构建成功,起点: {startRow}-{startColumn}-{startLayer},终点: {router.SrmRow}-{router.SrmColumn}-{router.SrmLayer}", task.Roadway, startRow, startColumn, startLayer, router.SrmRow, router.SrmColumn, router.SrmLayer, task.TaskNum);
            return command;
        }
@@ -327,14 +314,12 @@
        /// <returns>填充好的命令对象</returns>
        private T? BuildRelocationCommand<T>(Dt_Task task, T command) where T : class
        {
            _logger.LogInformation("BuildRelocationCommand:构建移库命令,任务号: {TaskNum}", task.TaskNum);
            QuartzLogger.Info($"BuildRelocationCommand:构建移库命令,任务号: {task.TaskNum}", task.Roadway);
            QuartzLogHelper.LogInfo(_logger, "BuildRelocationCommand:构建移库命令,任务号: {TaskNum}", $"BuildRelocationCommand:构建移库命令,任务号: {task.TaskNum}", task.Roadway, task.TaskNum);
            // è§£æžç›®æ ‡åœ°å€
            if (!TryParseAddress(task.NextAddress, out short endRow, out short endColumn, out short endLayer))
            {
                _logger.LogError("BuildRelocationCommand:移库任务终点地址解析失败,终点: {NextAddress},任务号: {TaskNum}", task.NextAddress, task.TaskNum);
                QuartzLogger.Error($"BuildRelocationCommand:移库任务终点地址解析失败,终点: {task.NextAddress}", task.Roadway);
                QuartzLogHelper.LogError(_logger, "BuildRelocationCommand:移库任务终点地址解析失败,终点: {NextAddress},任务号: {TaskNum}", $"BuildRelocationCommand:移库任务终点地址解析失败,终点: {task.NextAddress}", task.Roadway, task.NextAddress, task.TaskNum);
                _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"移库任务终点错误,终点:【{task.NextAddress}】");
                return null;
            }
@@ -347,8 +332,7 @@
            // è§£æžèµ·å§‹åœ°å€
            if (!TryParseAddress(task.CurrentAddress, out short startRow, out short startColumn, out short startLayer))
            {
                _logger.LogError("BuildRelocationCommand:移库任务起点地址解析失败,起点: {CurrentAddress},任务号: {TaskNum}", task.CurrentAddress, task.TaskNum);
                QuartzLogger.Error($"BuildRelocationCommand:移库任务起点地址解析失败,起点: {task.CurrentAddress}", task.Roadway);
                QuartzLogHelper.LogError(_logger, "BuildRelocationCommand:移库任务起点地址解析失败,起点: {CurrentAddress},任务号: {TaskNum}", $"BuildRelocationCommand:移库任务起点地址解析失败,起点: {task.CurrentAddress}", task.Roadway, task.CurrentAddress, task.TaskNum);
                _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"移库任务起点错误,起点:【{task.CurrentAddress}】");
                return null;
            }
@@ -358,9 +342,7 @@
            SetCommandProperty(command, "StartColumn", startColumn);
            SetCommandProperty(command, "StartLayer", startLayer);
            _logger.LogInformation("BuildRelocationCommand:移库命令构建成功,起点: {StartRow}-{StartColumn}-{StartLayer},终点: {EndRow}-{EndColumn}-{EndLayer},任务号: {TaskNum}",
                startRow, startColumn, startLayer, endRow, endColumn, endLayer, task.TaskNum);
            QuartzLogger.Info($"BuildRelocationCommand:移库命令构建成功,起点: {startRow}-{startColumn}-{startLayer},终点: {endRow}-{endColumn}-{endLayer}", task.Roadway);
            QuartzLogHelper.LogInfo(_logger, "BuildRelocationCommand:移库命令构建成功,起点: {StartRow}-{StartColumn}-{StartLayer},终点: {EndRow}-{EndColumn}-{EndLayer},任务号: {TaskNum}", $"BuildRelocationCommand:移库命令构建成功,起点: {startRow}-{startColumn}-{startLayer},终点: {endRow}-{endColumn}-{endLayer}", task.Roadway, startRow, startColumn, startLayer, endRow, endColumn, endLayer, task.TaskNum);
            return command;
        }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs
@@ -109,8 +109,7 @@
            {
                // æ²¡æœ‰ä¸Šä¸€ä»»åŠ¡ç±»åž‹ï¼ŒæŸ¥è¯¢æ™®é€šä»»åŠ¡
                candidateTask = _taskService.QueryStackerCraneTask(deviceCode);
                _logger.LogDebug("SelectTask:查询普通任务,设备: {DeviceCode},结果: {TaskNum}", deviceCode, candidateTask?.TaskNum);
                QuartzLogger.Debug($"查询普通任务,设备: {deviceCode},结果: {candidateTask?.TaskNum}", deviceCode);
                QuartzLogHelper.LogDebug(_logger, "SelectTask:查询普通任务,设备: {DeviceCode},结果: {TaskNum}", $"查询普通任务,设备: {deviceCode},结果: {candidateTask?.TaskNum}", deviceCode, deviceCode, candidateTask?.TaskNum);
            }
            else if (commonStackerCrane.LastTaskType.GetValueOrDefault().GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup)
            {
@@ -118,30 +117,26 @@
                candidateTask = _taskService.QueryStackerCraneInTask(deviceCode);
                // å¦‚果没有入库任务,再查一下出库任务
                candidateTask ??= _taskService.QueryStackerCraneOutTask(deviceCode);
                _logger.LogDebug("SelectTask:出库后优先查入库,设备: {DeviceCode},结果: {TaskNum}", deviceCode, candidateTask?.TaskNum);
                QuartzLogger.Debug($"出库后优先查入库,设备: {deviceCode},结果: {candidateTask?.TaskNum}", deviceCode);
                QuartzLogHelper.LogDebug(_logger, "SelectTask:出库后优先查入库,设备: {DeviceCode},结果: {TaskNum}", $"出库后优先查入库,设备: {deviceCode},结果: {candidateTask?.TaskNum}", deviceCode, deviceCode, candidateTask?.TaskNum);
            }
            else
            {
                // ä¸Šä¸€ä»»åŠ¡æ˜¯å…¥åº“ï¼ˆéžå‡ºåº“ï¼‰ï¼Œä¼˜å…ˆæŸ¥å‡ºåº“ä»»åŠ¡
                candidateTask = _taskService.QueryStackerCraneOutTask(deviceCode);
                _logger.LogDebug("SelectTask:入库后优先查出库,设备: {DeviceCode},结果: {TaskNum}", deviceCode, candidateTask?.TaskNum);
                QuartzLogger.Debug($"入库后优先查出库,设备: {deviceCode},结果: {candidateTask?.TaskNum}", deviceCode);
                QuartzLogHelper.LogDebug(_logger, "SelectTask:入库后优先查出库,设备: {DeviceCode},结果: {TaskNum}", $"入库后优先查出库,设备: {deviceCode},结果: {candidateTask?.TaskNum}", deviceCode, deviceCode, candidateTask?.TaskNum);
            }
            // å¦‚果没有候选任务,返回 null
            if (candidateTask == null)
            {
                _logger.LogDebug("SelectTask:没有候选任务,设备: {DeviceCode}", deviceCode);
                QuartzLogger.Debug($"没有候选任务,设备: {deviceCode}", deviceCode);
                QuartzLogHelper.LogDebug(_logger, "SelectTask:没有候选任务,设备: {DeviceCode}", $"没有候选任务,设备: {deviceCode}", deviceCode, deviceCode);
                return null;
            }
            // å¦‚果不是出库任务,直接返回
            if (candidateTask.TaskType.GetTaskTypeGroup() != TaskTypeGroup.OutbondGroup)
            {
                _logger.LogInformation("SelectTask:选中非出库任务,设备: {DeviceCode},任务号: {TaskNum},任务类型: {TaskType}", deviceCode, candidateTask.TaskNum, candidateTask.TaskType);
                QuartzLogger.Info($"选中非出库任务,任务号: {candidateTask.TaskNum},任务类型: {candidateTask.TaskType}", deviceCode);
                QuartzLogHelper.LogInfo(_logger, "SelectTask:选中非出库任务,设备: {DeviceCode},任务号: {TaskNum},任务类型: {TaskType}", $"选中非出库任务,任务号: {candidateTask.TaskNum},任务类型: {candidateTask.TaskType}", deviceCode, deviceCode, candidateTask.TaskNum, candidateTask.TaskType);
                return candidateTask;
            }
@@ -149,8 +144,7 @@
            Dt_Task? selectedTask = TrySelectOutboundTask(candidateTask);
            if (selectedTask != null)
            {
                _logger.LogInformation("SelectTask:选中出库任务,设备: {DeviceCode},任务号: {TaskNum}", deviceCode, selectedTask.TaskNum);
                QuartzLogger.Info($"选中出库任务,任务号: {selectedTask.TaskNum}", deviceCode);
                QuartzLogHelper.LogInfo(_logger, "SelectTask:选中出库任务,设备: {DeviceCode},任务号: {TaskNum}", $"选中出库任务,任务号: {selectedTask.TaskNum}", deviceCode, deviceCode, selectedTask.TaskNum);
                return selectedTask;
            }
@@ -167,16 +161,14 @@
                selectedTask = TrySelectOutboundTask(alternativeTask);
                if (selectedTask != null)
                {
                    _logger.LogInformation("SelectTask:选中备选出库任务,设备: {DeviceCode},任务号: {TaskNum}", deviceCode, selectedTask.TaskNum);
                    QuartzLogger.Info($"选中备选出库任务,任务号: {selectedTask.TaskNum}", deviceCode);
                    QuartzLogHelper.LogInfo(_logger, "SelectTask:选中备选出库任务,设备: {DeviceCode},任务号: {TaskNum}", $"选中备选出库任务,任务号: {selectedTask.TaskNum}", deviceCode, deviceCode, selectedTask.TaskNum);
                    return selectedTask;
                }
            }
            // æ²¡æœ‰å¯ç”¨å‡ºåº“任务,尝试返回入库任务
            var inboundTask = _taskService.QueryStackerCraneInTask(deviceCode);
            _logger.LogInformation("SelectTask:返回入库任务,设备: {DeviceCode},任务号: {TaskNum}", deviceCode, inboundTask?.TaskNum);
            QuartzLogger.Info($"返回入库任务,任务号: {inboundTask?.TaskNum}", deviceCode);
            QuartzLogHelper.LogInfo(_logger, "SelectTask:返回入库任务,设备: {DeviceCode},任务号: {TaskNum}", $"返回入库任务,任务号: {inboundTask?.TaskNum}", deviceCode, deviceCode, inboundTask?.TaskNum);
            return inboundTask;
        }
@@ -299,8 +291,7 @@
            if (router == null)
            {
                // æœªæ‰¾åˆ°ç«™å°è·¯ç”±ä¿¡æ¯
                _logger.LogWarning("IsOutTaskStationAvailable:未找到站台路由信息,站台: {NextAddress},任务号: {TaskNum}", task.NextAddress, task.TaskNum);
                QuartzLogger.Warn($"IsOutTaskStationAvailable:未找到站台路由信息,站台: {task.NextAddress}", task.Roadway);
                QuartzLogHelper.LogWarn(_logger, "IsOutTaskStationAvailable:未找到站台路由信息,站台: {NextAddress},任务号: {TaskNum}", $"IsOutTaskStationAvailable:未找到站台路由信息,站台: {task.NextAddress}", task.Roadway, task.NextAddress, task.TaskNum);
                _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.NextAddress}】信息,无法校验站台");
                return false;
            }
@@ -310,8 +301,7 @@
            if (device == null)
            {
                // æœªæ‰¾åˆ°è®¾å¤‡
                _logger.LogWarning("IsOutTaskStationAvailable:未找到出库站台对应的通讯对象,站台: {ChildPosiDeviceCode},任务号: {TaskNum}", router.ChildPosiDeviceCode, task.TaskNum);
                QuartzLogger.Warn($"IsOutTaskStationAvailable:未找到出库站台对应的通讯对象,站台: {router.ChildPosiDeviceCode}", task.Roadway);
                QuartzLogHelper.LogWarn(_logger, "IsOutTaskStationAvailable:未找到出库站台对应的通讯对象,站台: {ChildPosiDeviceCode},任务号: {TaskNum}", $"IsOutTaskStationAvailable:未找到出库站台对应的通讯对象,站台: {router.ChildPosiDeviceCode}", task.Roadway, router.ChildPosiDeviceCode, task.TaskNum);
                _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到出库站台【{router.ChildPosiDeviceCode}】对应的通讯对象,无法判断出库站台是否被占用");
                return false;
            }
@@ -321,8 +311,7 @@
            // æ£€æŸ¥ç«™å°æ˜¯å¦è¢«å ç”¨
            bool isOccupied = conveyorLine.IsOccupied(router.ChildPosi);
            _logger.LogInformation("IsOutTaskStationAvailable:站台 {ChildPosi},是否被占用: {IsOccupied},任务号: {TaskNum}", router.ChildPosi, !isOccupied, task.TaskNum);
            QuartzLogger.Info($"IsOutTaskStationAvailable:站台 {router.ChildPosi},是否被占用: {!isOccupied}", task.Roadway);
            QuartzLogHelper.LogInfo(_logger, "IsOutTaskStationAvailable:站台 {ChildPosi},是否被占用: {IsOccupied},任务号: {TaskNum}", $"IsOutTaskStationAvailable:站台 {router.ChildPosi},是否被占用: {!isOccupied}", task.Roadway, router.ChildPosi, !isOccupied, task.TaskNum);
            return isOccupied;
        }
Code/WMS/WIDESEA_WMSClient/src/extension/taskinfo/extend/gridBodyExtension.vue
@@ -60,7 +60,8 @@
        </el-table-column>
        <el-table-column prop="grade" label="优先级" width="100">
          <template v-slot="{ row }">
            <el-input-number v-if="row && row.editable" v-model="row.grade" :min="1" :max="99" size="small" style="width: 80px"></el-input-number>
            <el-input-number v-if="row && row.editable" v-model="row.grade" :min="1" :max="99" size="small"
              style="width: 80px"></el-input-number>
            <span v-else>{{ row ? row.grade : '' }}</span>
          </template>
        </el-table-column>
@@ -242,7 +243,9 @@
    },
    getStatusKey(taskType, taskStatus) {
      if (taskType === 200) return `inbound_${taskStatus}`;
      if (taskType === 204) return `inbound_${taskStatus}`;
      if (taskType === 100) return `outbound_${taskStatus}`;
      if (taskType === 140) return `outbound_${taskStatus}`;
      if (taskType === 300) return `relocation_${taskStatus}`;
      return `other_${taskStatus}`;
    },
@@ -250,6 +253,8 @@
      if (taskType === 200 && taskStatus === 200) return true;
      if (taskType === 100 && taskStatus === 100) return true;
      if (taskType === 300 && taskStatus === 300) return true;
      if (taskType === 140 && taskStatus === 100) return true;
      if (taskType === 204 && taskStatus === 200) return true;
      return false;
    },
    submitDispatch() {
@@ -308,19 +313,23 @@
  color: #606266;
  margin-bottom: 10px;
}
.dispatch-info .count {
  color: #409eff;
  font-weight: bold;
}
.status-error {
  color: #f56c6c;
}
.fail-results {
  margin-top: 15px;
  padding: 10px;
  background: #fef0f0;
  border-radius: 4px;
}
.fail-title {
  font-size: 14px;
  color: #f56c6c;
Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/TaskEnum/TaskTypeEnum.cs
@@ -128,7 +128,7 @@
        /// ç©ºç®±å…¥åº“
        /// </summary>
        [Description("空箱入库")]
        InEmpty = 600,
        InEmpty = 204,
    }
    public enum TaskOutboundTypeEnum
Code/²âÊÔ¹¤¾ß/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Data/instance-1003/config.json
@@ -2,7 +2,7 @@
  "id": "1003",
  "name": "A\u533A_\u5E38\u6E29\u8F93\u9001\u7EBF",
  "plcType": "S71500",
  "port": 109,
  "port": 102,
  "activationKey": "",
  "autoStart": false,
  "protocolTemplateId": "protocol-1003",
Code/²âÊÔ¹¤¾ß/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Data/instance-CWSC1/config.json
@@ -2,7 +2,7 @@
  "id": "CWSC1",
  "name": "\u5E38\u6E29\u5806\u579B\u673A",
  "plcType": "S71500",
  "port": 103,
  "port": 102,
  "activationKey": "",
  "autoStart": false,
  "protocolTemplateId": "protocol-CWSC1",
Code/²âÊÔ¹¤¾ß/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Data/instance-HCSC1/config.json
@@ -2,16 +2,15 @@
  "id": "HCSC1",
  "name": "\u5316\u6210\u5806\u579B\u673A",
  "plcType": "S71500",
  "port": 104,
  "port": 102,
  "activationKey": "",
  "autoStart": false,
  "protocolTemplateId": "protocol-HCSC1",
  "memoryConfig": {
    "mRegionSize": 1024,
    "dbBlockCount": 2,
    "dbBlockCount": 1,
    "dbBlockNumbers": [
      910,
      900
      510
    ],
    "dbBlockSize": 65536,
    "iRegionSize": 256,
Code/²âÊÔ¹¤¾ß/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Data/instance-PM/config.json
@@ -2,7 +2,7 @@
  "id": "PM",
  "name": "\u63D2\u62D4\u9489\u673A",
  "plcType": "S71500",
  "port": 107,
  "port": 102,
  "activationKey": "",
  "autoStart": false,
  "protocolTemplateId": "protocol-PM",
Code/²âÊÔ¹¤¾ß/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Server/Data/protocol-templates.json
@@ -5,7 +5,7 @@
    "version": "1.0",
    "fields": [
      {
        "fieldKey": "GWSC01_InputTaskNum",
        "fieldKey": "GWSC1_InputTaskNum",
        "dbNumber": 100,
        "offset": 194,
        "bit": 1,
@@ -14,7 +14,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_WorkAction",
        "fieldKey": "GWSC1_WorkAction",
        "dbNumber": 100,
        "offset": 192,
        "bit": 1,
@@ -23,7 +23,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_InputWorkType",
        "fieldKey": "GWSC1_InputWorkType",
        "dbNumber": 100,
        "offset": 198,
        "bit": 1,
@@ -32,7 +32,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_InputPickRow",
        "fieldKey": "GWSC1_InputPickRow",
        "dbNumber": 100,
        "offset": 208,
        "bit": 1,
@@ -41,7 +41,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_InputPickColumn",
        "fieldKey": "GWSC1_InputPickColumn",
        "dbNumber": 100,
        "offset": 210,
        "bit": 1,
@@ -50,7 +50,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_InputPickLayer",
        "fieldKey": "GWSC1_InputPickLayer",
        "dbNumber": 100,
        "offset": 212,
        "bit": 1,
@@ -59,7 +59,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_InputPlaceRow",
        "fieldKey": "GWSC1_InputPlaceRow",
        "dbNumber": 100,
        "offset": 214,
        "bit": 1,
@@ -68,7 +68,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_InputPlaceColumn",
        "fieldKey": "GWSC1_InputPlaceColumn",
        "dbNumber": 100,
        "offset": 216,
        "bit": 1,
@@ -77,7 +77,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_InputPlaceLayer",
        "fieldKey": "GWSC1_InputPlaceLayer",
        "dbNumber": 100,
        "offset": 218,
        "bit": 1,
@@ -86,7 +86,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_StackerCraneAutoStatus",
        "fieldKey": "GWSC1_StackerCraneAutoStatus",
        "dbNumber": 100,
        "offset": 2,
        "bit": 1,
@@ -95,7 +95,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_StackerCraneWorkStatus",
        "fieldKey": "GWSC1_StackerCraneWorkStatus",
        "dbNumber": 100,
        "offset": 4,
        "bit": 1,
@@ -104,7 +104,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_OutputFaultHigh",
        "fieldKey": "GWSC1_OutputFaultHigh",
        "dbNumber": 100,
        "offset": 12,
        "bit": 1,
@@ -113,7 +113,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_OutputFaultMid",
        "fieldKey": "GWSC1_OutputFaultMid",
        "dbNumber": 100,
        "offset": 16,
        "bit": 1,
@@ -122,7 +122,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_OutputFaultLow",
        "fieldKey": "GWSC1_OutputFaultLow",
        "dbNumber": 100,
        "offset": 20,
        "bit": 1,
@@ -131,7 +131,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_CurrentTaskNum",
        "fieldKey": "GWSC1_CurrentTaskNum",
        "dbNumber": 100,
        "offset": 24,
        "bit": 1,
@@ -140,7 +140,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_StackerCraneCompleted",
        "fieldKey": "GWSC1_StackerCraneCompleted",
        "dbNumber": 100,
        "offset": 28,
        "bit": 1,
@@ -149,7 +149,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_OutputCurrentColumn",
        "fieldKey": "GWSC1_OutputCurrentColumn",
        "dbNumber": 100,
        "offset": 46,
        "bit": 1,
@@ -158,7 +158,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_OutputCurrentLayer",
        "fieldKey": "GWSC1_OutputCurrentLayer",
        "dbNumber": 100,
        "offset": 48,
        "bit": 1,
@@ -167,7 +167,7 @@
        "direction": 2
      },
      {
        "fieldKey": "GWSC01_StackerCraneStatus",
        "fieldKey": "GWSC1_StackerCraneStatus",
        "dbNumber": 100,
        "offset": 96,
        "bit": 1,
@@ -183,62 +183,17 @@
    "version": "1.0",
    "fields": [
      {
        "fieldKey": "HCSC01_StackerCraneHeartBeat",
        "dbNumber": 910,
        "fieldKey": "HCSC1_InputTaskNum",
        "dbNumber": 510,
        "offset": 0,
        "bit": 1,
        "dataType": 1,
        "dataType": 2,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_StackerCraneStatus",
        "dbNumber": 910,
        "offset": 6,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_StackerCraneFaultCode",
        "dbNumber": 910,
        "offset": 8,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_StackerCraneWorkStatus",
        "dbNumber": 910,
        "offset": 20,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_StackerCraneRow",
        "dbNumber": 910,
        "offset": 22,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_StackerCraneColumn",
        "dbNumber": 910,
        "offset": 24,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_StackerCraneLayer",
        "dbNumber": 910,
        "fieldKey": "HCSC1_WorkAction",
        "dbNumber": 510,
        "offset": 26,
        "bit": 1,
        "dataType": 1,
@@ -246,107 +201,125 @@
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_CurrentTaskNum",
        "dbNumber": 910,
        "fieldKey": "HCSC1_InputWorkType",
        "dbNumber": 510,
        "offset": 4,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC1_InputPickRow",
        "dbNumber": 510,
        "offset": 14,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC1_InputPickColumn",
        "dbNumber": 510,
        "offset": 16,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC1_InputPickLayer",
        "dbNumber": 510,
        "offset": 18,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC1_InputPlaceRow",
        "dbNumber": 510,
        "offset": 20,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC1_InputPlaceColumn",
        "dbNumber": 510,
        "offset": 22,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC1_InputPlaceLayer",
        "dbNumber": 510,
        "offset": 24,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC1_StackerCraneAutoStatus",
        "dbNumber": 510,
        "offset": 28,
        "bit": 1,
        "dataType": 2,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_StackerCraneWorkAction",
        "dbNumber": 910,
        "offset": 40,
        "fieldKey": "HCSC1_StackerCraneWorkStatus",
        "dbNumber": 510,
        "offset": 30,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_StackerCraneCompleted",
        "dbNumber": 910,
        "offset": 42,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_HeartBeat",
        "dbNumber": 900,
        "offset": 0,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_TaskNum",
        "dbNumber": 900,
        "offset": 2,
        "fieldKey": "HCSC1_OutputFaultHigh",
        "dbNumber": 510,
        "offset": 32,
        "bit": 1,
        "dataType": 2,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_WorkAction",
        "dbNumber": 900,
        "fieldKey": "HCSC1_OutputFaultMid",
        "dbNumber": 510,
        "offset": 36,
        "bit": 1,
        "dataType": 2,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC1_OutputFaultLow",
        "dbNumber": 510,
        "offset": 40,
        "bit": 1,
        "dataType": 1,
        "dataType": 2,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_FireAlarm",
        "dbNumber": 900,
        "offset": 42,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_WorkType",
        "dbNumber": 900,
        "offset": 44,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_StartRow",
        "dbNumber": 900,
        "offset": 46,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_StartColumn",
        "dbNumber": 900,
        "fieldKey": "HCSC1_CurrentTaskNum",
        "dbNumber": 510,
        "offset": 48,
        "bit": 1,
        "dataType": 1,
        "dataType": 2,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_StartLayer",
        "dbNumber": 900,
        "offset": 50,
        "bit": 1,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_EndRow",
        "dbNumber": 900,
        "fieldKey": "HCSC1_StackerCraneCompleted",
        "dbNumber": 510,
        "offset": 52,
        "bit": 1,
        "dataType": 1,
@@ -354,8 +327,8 @@
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_EndColumn",
        "dbNumber": 900,
        "fieldKey": "HCSC1_OutputCurrentColumn",
        "dbNumber": 510,
        "offset": 54,
        "bit": 1,
        "dataType": 1,
@@ -363,8 +336,8 @@
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_EndLayer",
        "dbNumber": 900,
        "fieldKey": "HCSC1_OutputCurrentLayer",
        "dbNumber": 510,
        "offset": 56,
        "bit": 1,
        "dataType": 1,
@@ -372,12 +345,21 @@
        "direction": 2
      },
      {
        "fieldKey": "HCSC01_Barcode",
        "dbNumber": 900,
        "fieldKey": "HCSC1_StackerCraneStatus",
        "dbNumber": 510,
        "offset": 58,
        "bit": 1,
        "dataType": 3,
        "length": 26,
        "dataType": 1,
        "length": 1,
        "direction": 2
      },
      {
        "fieldKey": "HCSC1_OutputFaultLow1",
        "dbNumber": 510,
        "offset": 44,
        "bit": 1,
        "dataType": 2,
        "length": 1,
        "direction": 2
      }
    ]
@@ -388,7 +370,7 @@
    "version": "1.0",
    "fields": [
      {
        "fieldKey": "CWSC01_InputTaskNum",
        "fieldKey": "CWSC1_InputTaskNum",
        "dbNumber": 100,
        "offset": 194,
        "bit": 1,
@@ -397,7 +379,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_WorkAction",
        "fieldKey": "CWSC1_WorkAction",
        "dbNumber": 100,
        "offset": 192,
        "bit": 1,
@@ -406,7 +388,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_InputWorkType",
        "fieldKey": "CWSC1_InputWorkType",
        "dbNumber": 100,
        "offset": 198,
        "bit": 1,
@@ -415,7 +397,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_InputPickRow",
        "fieldKey": "CWSC1_InputPickRow",
        "dbNumber": 100,
        "offset": 208,
        "bit": 1,
@@ -424,7 +406,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_InputPickColumn",
        "fieldKey": "CWSC1_InputPickColumn",
        "dbNumber": 100,
        "offset": 210,
        "bit": 1,
@@ -433,7 +415,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_InputPickLayer",
        "fieldKey": "CWSC1_InputPickLayer",
        "dbNumber": 100,
        "offset": 212,
        "bit": 1,
@@ -442,7 +424,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_InputPlaceRow",
        "fieldKey": "CWSC1_InputPlaceRow",
        "dbNumber": 100,
        "offset": 214,
        "bit": 1,
@@ -451,7 +433,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_InputPlaceColumn",
        "fieldKey": "CWSC1_InputPlaceColumn",
        "dbNumber": 100,
        "offset": 216,
        "bit": 1,
@@ -460,7 +442,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_InputPlaceLayer",
        "fieldKey": "CWSC1_InputPlaceLayer",
        "dbNumber": 100,
        "offset": 218,
        "bit": 1,
@@ -469,7 +451,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_StackerCraneAutoStatus",
        "fieldKey": "CWSC1_StackerCraneAutoStatus",
        "dbNumber": 100,
        "offset": 2,
        "bit": 1,
@@ -478,7 +460,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_StackerCraneWorkStatus",
        "fieldKey": "CWSC1_StackerCraneWorkStatus",
        "dbNumber": 100,
        "offset": 4,
        "bit": 1,
@@ -487,7 +469,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_OutputFaultHigh",
        "fieldKey": "CWSC1_OutputFaultHigh",
        "dbNumber": 100,
        "offset": 12,
        "bit": 1,
@@ -496,7 +478,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_OutputFaultMid",
        "fieldKey": "CWSC1_OutputFaultMid",
        "dbNumber": 100,
        "offset": 16,
        "bit": 1,
@@ -505,7 +487,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_OutputFaultLow",
        "fieldKey": "CWSC1_OutputFaultLow",
        "dbNumber": 100,
        "offset": 20,
        "bit": 1,
@@ -514,7 +496,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_CurrentTaskNum",
        "fieldKey": "CWSC1_CurrentTaskNum",
        "dbNumber": 100,
        "offset": 24,
        "bit": 1,
@@ -523,7 +505,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_StackerCraneCompleted",
        "fieldKey": "CWSC1_StackerCraneCompleted",
        "dbNumber": 100,
        "offset": 28,
        "bit": 1,
@@ -532,7 +514,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_OutputCurrentColumn",
        "fieldKey": "CWSC1_OutputCurrentColumn",
        "dbNumber": 100,
        "offset": 46,
        "bit": 1,
@@ -541,7 +523,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_OutputCurrentLayer",
        "fieldKey": "CWSC1_OutputCurrentLayer",
        "dbNumber": 100,
        "offset": 48,
        "bit": 1,
@@ -550,7 +532,7 @@
        "direction": 2
      },
      {
        "fieldKey": "CWSC01_StackerCraneStatus",
        "fieldKey": "CWSC1_StackerCraneStatus",
        "dbNumber": 100,
        "offset": 96,
        "bit": 1,