From ce1292c9cf37195b6abd2699dfc5d6cb3e143c9b Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期日, 12 四月 2026 23:38:19 +0800
Subject: [PATCH] feat(MES): 添加MES接口相关实体和DTO JS扩展文件至JSX格式并更新配置
---
Code/docs/superpowers/plans/2026-04-11-manual-task-creation-plan.md | 434 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 434 insertions(+), 0 deletions(-)
diff --git a/Code/docs/superpowers/plans/2026-04-11-manual-task-creation-plan.md b/Code/docs/superpowers/plans/2026-04-11-manual-task-creation-plan.md
new file mode 100644
index 0000000..c1902be
--- /dev/null
+++ b/Code/docs/superpowers/plans/2026-04-11-manual-task-creation-plan.md
@@ -0,0 +1,434 @@
+# 鎵嬪姩鍒涘缓浠诲姟鍔熻兘瀹炴柦璁″垝
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** 鍦╓MS鐣岄潰涓婃坊鍔犳墜鍔ㄥ垱寤轰换鍔″姛鑳斤紝鏀寔鍏ュ簱/鍑哄簱/绉诲簱涓夌绫诲瀷锛屼换鍔″彂閫佽嚦WCS鍚庯紝WCS鍒ゆ柇璧风偣涓虹嚎浣撶偣浣�(11068/11010/11001)鏃跺啓鍏ヨ緭閫佺嚎浠诲姟銆�
+
+**Architecture:** WMS鍓嶇Vue椤甸潰 鈫� WMS鍚庣API 鈫� WCS ReceiveTask 鈫� WCS FlowService鍒ゆ柇骞跺啓鍏ヨ緭閫佺嚎PLC
+
+**Tech Stack:** .NET 6 (WMS/WCS Backend), Vue3 (WMS Frontend), MapsterMapper, SqlSugar
+
+---
+
+## 鏂囦欢缁撴瀯
+
+| 鏂囦欢 | 鑱岃矗 |
+|------|------|
+| `WMS/WIDESEA_WMSClient/src/extension/taskinfo/task.js` | 娣诲姞鎵嬪姩鍒涘缓浠诲姟鎸夐挳鍜屽鐞嗛�昏緫 |
+| `WMS/WIDESEA_WMSServer/WIDESEA_DTO/Task/CreateManualTaskDto.cs` | **鏂板缓** - 鎵嬪姩鍒涘缓浠诲姟璇锋眰DTO |
+| `WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/TaskInfo/TaskController.cs` | 娣诲姞 CreateManualTask 鎺ュ彛 |
+| `WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs` | 娣诲姞 CreateManualTaskAsync 鏂规硶 |
+| `WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs` | ReceiveWMSTask 宸叉湁鍒嗗彂閫昏緫锛岀‘璁ゅ叆鍙f纭� |
+| `WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/InboundTaskFlowService.cs` | 娣诲姞绾夸綋鐐逛綅鍒ゆ柇鍜岃緭閫佺嚎浠诲姟鍐欏叆閫昏緫 |
+
+---
+
+## WMS 鍓嶇
+
+### Task 1: 娣诲姞鎵嬪姩鍒涘缓浠诲姟鎸夐挳
+
+**鏂囦欢:**
+- Modify: `WMS/WIDESEA_WMSClient/src/extension/taskinfo/task.js:16`
+
+- [ ] **Step 1: 鍦� buttons.box 娣诲姞鎵嬪姩鍒涘缓鎸夐挳**
+
+鍦� `task.js` 鐨� `buttons: { view: [], box: [], detail: [] }` 涓坊鍔狅細
+
+```javascript
+buttons: {
+ view: [],
+ box: [
+ {
+ value: 'CreateManualTask',
+ label: '鎵嬪姩鍒涘缓浠诲姟',
+ onClick: function () {
+ // 寮瑰嚭鎵嬪姩鍒涘缓浠诲姟瀵硅瘽妗�
+ this.$refs.grid.openModel('Add');
+ }
+ }
+ ],
+ detail: []
+},
+```
+
+- [ ] **Step 2: 鍦� modelFooter 娣诲姞鑷畾涔夊脊绐�**
+
+鍦� `components.modelFooter` 娣诲姞 Vue 妯℃澘锛堝鏋滄鏋舵敮鎸佽嚜瀹氫箟寮圭獥鍐呭锛夛紝鎴栦娇鐢ㄦ鏋跺唴缃殑 `openModel` 閰嶅悎 `addBefore` 澶勭悊銆�
+
+> **娉ㄦ剰:** 鍏蜂綋鐨勫脊绐楀疄鐜板彇鍐充簬褰撳墠鍓嶇妗嗘灦鐨勬墿灞曟満鍒躲�傝嫢褰撳墠椤甸潰涓嶆敮鎸佽嚜瀹氫箟瀛楁锛屽垯闇�瑕佸湪 `task.vue` 涓坊鍔犳柊鐨勯〉闈㈢粍浠讹紝鎴栭�氳繃 `modelBody` 鎵╁睍鑷畾涔夎〃鍗曘��
+
+- [ ] **Step 3: 鎻愪氦**
+
+```bash
+git add WMS/WIDESEA_WMSClient/src/extension/taskinfo/task.js
+git commit -m "feat(WMS): 娣诲姞鎵嬪姩鍒涘缓浠诲姟鎸夐挳"
+```
+
+---
+
+## WMS 鍚庣
+
+### Task 2: 鍒涘缓 DTO
+
+**鏂囦欢:**
+- Create: `WMS/WIDESEA_WMSServer/WIDESEA_DTO/Task/CreateManualTaskDto.cs`
+
+- [ ] **Step 1: 缂栧啓 CreateManualTaskDto**
+
+```csharp
+using System.ComponentModel.DataAnnotations;
+using System.Text.Json.Serialization;
+using WIDESEA_Common.TaskEnum;
+
+namespace WIDESEA_DTO.Task
+{
+ /// <summary>
+ /// 鎵嬪姩鍒涘缓浠诲姟璇锋眰DTO
+ /// </summary>
+ public class CreateManualTaskDto
+ {
+ /// <summary>
+ /// 浠诲姟绫诲瀷锛�1=鍏ュ簱, 2=鍑哄簱, 3=绉诲簱
+ /// </summary>
+ [JsonPropertyName("taskType")]
+ [Required(ErrorMessage = "浠诲姟绫诲瀷涓嶈兘涓虹┖")]
+ public TaskTypeEnum TaskType { get; set; }
+
+ /// <summary>
+ /// 璧风偣鍦板潃
+ /// </summary>
+ [JsonPropertyName("sourceAddress")]
+ [Required(ErrorMessage = "璧风偣鍦板潃涓嶈兘涓虹┖")]
+ public string SourceAddress { get; set; }
+
+ /// <summary>
+ /// 缁堢偣鍦板潃
+ /// </summary>
+ [JsonPropertyName("targetAddress")]
+ [Required(ErrorMessage = "缁堢偣鍦板潃涓嶈兘涓虹┖")]
+ public string TargetAddress { get; set; }
+
+ /// <summary>
+ /// 鏉$爜
+ /// </summary>
+ [JsonPropertyName("barcode")]
+ [Required(ErrorMessage = "鏉$爜涓嶈兘涓虹┖")]
+ public string Barcode { get; set; }
+
+ /// <summary>
+ /// 浠撳簱ID
+ /// </summary>
+ [JsonPropertyName("warehouseId")]
+ [Required(ErrorMessage = "浠撳簱ID涓嶈兘涓虹┖")]
+ public int WarehouseId { get; set; }
+
+ /// <summary>
+ /// 浼樺厛绾э紝榛樿1
+ /// </summary>
+ [JsonPropertyName("grade")]
+ public int Grade { get; set; } = 1;
+ }
+}
+```
+
+- [ ] **Step 2: 鎻愪氦**
+
+```bash
+git add WMS/WIDESEA_WMSServer/WIDESEA_DTO/Task/CreateManualTaskDto.cs
+git commit -m "feat(WMS): 鏂板CreateManualTaskDto"
+```
+
+---
+
+### Task 3: 娣诲姞 Controller 鎺ュ彛
+
+**鏂囦欢:**
+- Modify: `WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/TaskInfo/TaskController.cs`
+
+- [ ] **Step 1: 娣诲姞 CreateManualTask 鎺ュ彛**
+
+鍦� `TaskController` 绫讳腑娣诲姞锛�
+
+```csharp
+/// <summary>
+/// 鎵嬪姩鍒涘缓浠诲姟
+/// </summary>
+/// <param name="dto">鎵嬪姩鍒涘缓浠诲姟鍙傛暟</param>
+/// <returns></returns>
+[HttpGet, HttpPost, Route("CreateManualTask"), AllowAnonymous]
+public async Task<WebResponseContent?> CreateManualTaskAsync([FromBody] CreateManualTaskDto dto)
+{
+ return await Service.CreateManualTaskAsync(dto);
+}
+```
+
+- [ ] **Step 2: 鎻愪氦**
+
+```bash
+git add WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/TaskInfo/TaskController.cs
+git commit -m "feat(WMS): 娣诲姞鎵嬪姩鍒涘缓浠诲姟鎺ュ彛 CreateManualTask"
+```
+
+---
+
+### Task 4: 娣诲姞 TaskService 鏂规硶
+
+**鏂囦欢:**
+- Modify: `WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs`
+
+棣栧厛鏌ョ湅鐜版湁 `TaskService.cs` 缁撴瀯锛岀‘璁ゆ柟娉曠鍚嶆牸寮忋��
+
+- [ ] **Step 1: 娣诲姞 CreateManualTaskAsync 鏂规硶**
+
+鍦� `TaskService` 绫讳腑娣诲姞锛堝弬鑰� `CreateAutoOutboundTasksAsync` 鐨勬ā寮忥級锛�
+
+```csharp
+/// <summary>
+/// 鎵嬪姩鍒涘缓浠诲姟
+/// </summary>
+/// <param name="dto">鎵嬪姩鍒涘缓浠诲姟鍙傛暟</param>
+/// <returns></returns>
+public async Task<WebResponseContent> CreateManualTaskAsync(CreateManualTaskDto dto)
+{
+ try
+ {
+ // 1. 鐢熸垚浠诲姟鍙�
+ int taskNum = await BaseDal.GetTaskNo();
+
+ // 2. 鏍规嵁浠诲姟绫诲瀷纭畾鐘舵�佸��
+ int taskStatus = dto.TaskType switch
+ {
+ TaskTypeEnum.Inbound => TaskInStatusEnum.InNew.GetHashCode(), // 200
+ TaskTypeEnum.Outbound => TaskOutStatusEnum.OutNew.GetHashCode(), // 100
+ TaskTypeEnum.Relocation => TaskRelocationStatusEnum.New.GetHashCode(), // 300
+ _ => TaskStatusEnum.New.GetHashCode()
+ };
+
+ // 3. 鏋勫缓浠诲姟瀹炰綋
+ var task = new Dt_Task
+ {
+ TaskNum = taskNum,
+ PalletCode = dto.Barcode,
+ SourceAddress = dto.SourceAddress,
+ TargetAddress = dto.TargetAddress,
+ TaskType = dto.TaskType.GetHashCode(),
+ TaskStatus = taskStatus,
+ Grade = dto.Grade,
+ WarehouseId = dto.WarehouseId,
+ Creater = "manual",
+ CreateDate = DateTime.Now,
+ ModifyDate = DateTime.Now
+ };
+
+ // 4. 淇濆瓨鍒版暟鎹簱
+ var result = await BaseDal.Add(task);
+ if (!result)
+ return WebResponseContent.Instance.Error("鍒涘缓浠诲姟澶辫触");
+
+ // 5. 鍙戦�佷换鍔″埌WCS
+ var wmsTaskDto = new WMSTaskDTO
+ {
+ TaskNum = task.TaskNum,
+ PalletCode = task.PalletCode,
+ SourceAddress = task.SourceAddress,
+ TargetAddress = task.TargetAddress,
+ TaskType = task.TaskType,
+ TaskStatus = task.TaskStatus,
+ WarehouseId = task.WarehouseId ?? 0
+ };
+
+ var wcsResult = await _httpClientHelper.PostAsync<WebResponseContent>(
+ "http://localhost:9292/api/Task/ReceiveTask",
+ wmsTaskDto.ToJson());
+
+ if (!wcsResult.IsSuccess || !wcsResult.Data.Status)
+ return WebResponseContent.Instance.Error($"浠诲姟宸插垱寤轰絾鍙戦�佺粰WCS澶辫触: {wcsResult.Data?.Message}");
+
+ return WebResponseContent.Instance.OK($"鎵嬪姩鍒涘缓浠诲姟鎴愬姛锛屼换鍔″彿: {taskNum}");
+ }
+ catch (Exception ex)
+ {
+ return WebResponseContent.Instance.Error($"鎵嬪姩鍒涘缓浠诲姟寮傚父: {ex.Message}");
+ }
+}
+```
+
+> **娉ㄦ剰:** 闇�瑕佺‘璁� `TaskRelocationStatusEnum` 鏄惁瀛樺湪锛屽涓嶅瓨鍦ㄥ垯浣跨敤 `TaskStatusEnum.New`銆�
+
+- [ ] **Step 2: 娣诲姞蹇呰鐨� using**
+
+```csharp
+using WIDESEA_DTO.Task;
+using WIDESEA_Common.TaskEnum;
+using WIDESEAWCS_DTO;
+```
+
+- [ ] **Step 3: 鎻愪氦**
+
+```bash
+git add WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs
+git commit -m "feat(WMS): 娣诲姞鎵嬪姩鍒涘缓浠诲姟 CreateManualTaskAsync 鏂规硶"
+```
+
+---
+
+## WCS 鍚庣
+
+### Task 5: 纭 ReceiveWMSTask 鍏ュ彛
+
+**鏂囦欢:**
+- Modify: `WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs`
+
+- [ ] **Step 1: 纭 ReceiveWMSTask 鏂规硶瀛樺湪**
+
+纭 `ReceiveWMSTask` 鎺ユ敹 `WMSTaskDTO` 鍒楄〃鍚庤矾鐢卞埌瀵瑰簲 FlowService銆�
+
+```csharp
+public WebResponseContent ReceiveWMSTask([NotNull] List<WMSTaskDTO> taskDTOs)
+{
+ // 閬嶅巻浠诲姟锛屾牴鎹� TaskType 鍒嗗彂鍒颁笉鍚� FlowService
+ foreach (var item in taskDTOs)
+ {
+ // 鏍规嵁 item.TaskType 鍒ゆ柇璺敱鍒� Inbound/Outbound/Relocation
+ }
+}
+```
+
+- [ ] **Step 2: 鎻愪氦**
+
+```bash
+git add WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs
+git commit -m "feat(WCS): 纭 ReceiveWMSTask 鍏ュ彛姝g‘"
+```
+
+---
+
+### Task 6: 鍦� InboundTaskFlowService 娣诲姞绾夸綋鐐逛綅澶勭悊
+
+**鏂囦欢:**
+- Modify: `WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/InboundTaskFlowService.cs`
+
+棣栧厛鏌ョ湅鐜版湁鐨� `InitializeOnReceive` 鏂规硶瀹屾暣瀹炵幇銆�
+
+- [ ] **Step 1: 娣诲姞绾夸綋鐐逛綅甯搁噺**
+
+鍦ㄧ被涓坊鍔狅細
+
+```csharp
+/// <summary>
+/// 绾夸綋鍏ュ簱鐐逛綅
+/// </summary>
+private static readonly string[] LINE_IN_POINTS = { "11068", "11010", "11001" };
+```
+
+- [ ] **Step 2: 淇敼 InitializeOnReceive 鏂规硶**
+
+鍦� `InitializeOnReceive` 鏂规硶涓紝鍒ゆ柇濡傛灉 `SourceAddress` 鏄嚎浣撶偣浣嶏紝鍒欏啓鍏ヨ緭閫佺嚎浠诲姟锛�
+
+```csharp
+public void InitializeOnReceive([NotNull] Dt_Task task, [NotNull] WMSTaskDTO source)
+{
+ // 鍏堟墽琛屽師鏈夌殑璺敱閫昏緫
+ Dt_Router routers = _routerService.QueryNextRoute(source.SourceAddress);
+ if (routers.IsNullOrEmpty())
+ {
+ return;
+ }
+
+ task.TaskStatus = (int)TaskInStatusEnum.InNew;
+ task.CurrentAddress = source.SourceAddress;
+ task.NextAddress = routers.ChildPosi;
+
+ // 濡傛灉璧风偣鏄嚎浣撶偣浣�(11068/11010/11001)锛岀洿鎺ュ啓鍏ヨ緭閫佺嚎浠诲姟
+ if (LINE_IN_POINTS.Contains(source.SourceAddress))
+ {
+ WriteConveyorLineTask(task, source.SourceAddress);
+ }
+}
+
+/// <summary>
+/// 鍐欏叆杈撻�佺嚎浠诲姟鍒癙LC
+/// </summary>
+private void WriteConveyorLineTask(Dt_Task task, string sourceAddress)
+{
+ // 1. 閫氳繃 Storage.Devices 鏌ユ壘瀵瑰簲鐨勮緭閫佺嚎璁惧
+ IDevice? device = Storage.Devices
+ .FirstOrDefault(x => x.DeviceProDTOs.Any(d => d.DeviceChildCode == sourceAddress));
+
+ if (device == null)
+ {
+ // 璁板綍鏃ュ織锛氭湭鎵惧埌瀵瑰簲鐨勮緭閫佺嚎璁惧
+ QuartzLogger.Error($"鎵嬪姩鍒涘缓浠诲姟锛氭湭鎵惧埌婧愬湴鍧�銆恵sourceAddress}銆戝搴旂殑杈撻�佺嚎璁惧", "InboundTaskFlowService");
+ return;
+ }
+
+ // 2. 杞崲涓� CommonConveyorLine 绫诲瀷
+ if (device is not CommonConveyorLine conveyorLine)
+ {
+ QuartzLogger.Error($"璁惧銆恵device.DeviceCode}銆戜笉鏄緭閫佺嚎绫诲瀷", "InboundTaskFlowService");
+ return;
+ }
+
+ // 3. 鑾峰彇瀛愯澶囩紪鐮�
+ string? childDeviceCode = device.DeviceProDTOs
+ .FirstOrDefault(d => d.DeviceChildCode == sourceAddress)?.DeviceChildCode;
+
+ if (string.IsNullOrEmpty(childDeviceCode))
+ {
+ QuartzLogger.Error($"婧愬湴鍧�銆恵sourceAddress}銆戞湭鎵惧埌瀵瑰簲鐨勫瓙璁惧缂栫爜", "InboundTaskFlowService");
+ return;
+ }
+
+ // 4. 鏋勯�� ConveyorLineTaskCommandNew
+ ConveyorLineTaskCommandNew command = new ConveyorLineTaskCommandNew
+ {
+ TaskNo = (short)task.TaskNum,
+ Source = short.Parse(sourceAddress),
+ Target = short.Parse(task.TargetAddress ?? "0"),
+ Barcode = task.PalletCode ?? string.Empty,
+ WCS_STB = 1, // WCS宸插彂閫佹爣蹇�
+ WCS_ACK = 0,
+ PLC_STB = 0,
+ PLC_ACK = 0
+ };
+
+ // 5. 鍐欏叆PLC
+ bool success = conveyorLine.SendCommand(command, childDeviceCode);
+ if (success)
+ {
+ QuartzLogger.Info($"鎵嬪姩鍒涘缓鍏ュ簱浠诲姟宸插啓鍏ヨ緭閫佺嚎锛氫换鍔″彿銆恵task.TaskNum}銆戯紝婧愬湴鍧�銆恵sourceAddress}銆�", conveyorLine.DeviceCode);
+ }
+ else
+ {
+ QuartzLogger.Error($"鎵嬪姩鍒涘缓鍏ュ簱浠诲姟鍐欏叆杈撻�佺嚎澶辫触锛氫换鍔″彿銆恵task.TaskNum}銆戯紝婧愬湴鍧�銆恵sourceAddress}銆�", conveyorLine.DeviceCode);
+ }
+}
+```
+
+- [ ] **Step 3: 娣诲姞蹇呰鐨� using**
+
+```csharp
+using WIDESEAWCS_QuartzJob;
+using WIDESEAWCS_QuartzJob.ConveyorLine;
+using WIDESEAWCS_Tasks;
+using WIDESEAWCS_Core.LogHelper;
+```
+
+- [ ] **Step 4: 鎻愪氦**
+
+```bash
+git add WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/InboundTaskFlowService.cs
+git commit -m "feat(WCS): 鍏ュ簱浠诲姟绾夸綋鐐逛綅鏃跺啓鍏ヨ緭閫佺嚎浠诲姟"
+```
+
+---
+
+## 楠岃瘉娓呭崟
+
+- [ ] WMS 鍓嶇锛氱偣鍑�"鎵嬪姩鍒涘缓浠诲姟"鎸夐挳寮瑰嚭瀵硅瘽妗�
+- [ ] WMS 鍓嶇锛氬~鍐欒〃鍗曞悗鎻愪氦锛岃繑鍥炴垚鍔�
+- [ ] WMS 鍚庣锛氬垱寤轰换鍔″啓鍏ユ暟鎹簱
+- [ ] WMS 鍚庣锛氫换鍔℃垚鍔熷彂閫佺粰 WCS
+- [ ] WCS 鍚庣锛歊eceiveTask 鏀跺埌浠诲姟
+- [ ] WCS 鍚庣锛氳捣鐐逛负绾夸綋鐐逛綅鏃讹紝浠诲姟鍐欏叆 PLC 鎴愬姛
+- [ ] WCS 鍚庣锛氳捣鐐逛负鏅�氱偣浣嶆椂锛岃蛋鍘熸湁璺敱閫昏緫
--
Gitblit v1.9.3