From 5bf17863fd36b8666e8b9f7a823a924f37a05354 Mon Sep 17 00:00:00 2001 From: liyongde <1419499670@qq.com> Date: Mon, 20 Jul 2026 13:49:32 +0800 Subject: [PATCH 1/8] =?UTF-8?q?fix:=20=E4=B8=8B=E6=B2=89=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E4=BD=93=E5=AF=B9=E8=B1=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/superpowers/plans/2026-07-14-task-core-implementation.md | 4 ++-- docs/superpowers/plans/2026-07-15-task-operation-refactor.md | 2 +- .../cn/code/nl/module/task}/message/TaskEventMessage.java | 2 +- .../nl/module/task/manage/TransportTaskOperationManager.java | 2 +- .../cn/code/nl/module/task/mq/producer/TaskEventProducer.java | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) rename nl-module-task/{nl-module-task-server/src/main/java/cn/code/nl/module/task/mq => nl-module-task-api/src/main/java/cn/code/nl/module/task}/message/TaskEventMessage.java (94%) diff --git a/docs/superpowers/plans/2026-07-14-task-core-implementation.md b/docs/superpowers/plans/2026-07-14-task-core-implementation.md index 504166a1..2a4934a5 100644 --- a/docs/superpowers/plans/2026-07-14-task-core-implementation.md +++ b/docs/superpowers/plans/2026-07-14-task-core-implementation.md @@ -793,7 +793,7 @@ git commit -m "feat: 新增 TransportTaskStatusClient 同步 HTTP 回调客户 ```java package cn.code.nl.module.task.mq; -import cn.code.nl.module.task.mq.message.TaskEventMessage; +import cn.code.nl.module.task.message.TaskEventMessage; import lombok.extern.slf4j.Slf4j; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.stereotype.Component; @@ -977,7 +977,7 @@ import cn.code.nl.module.task.client.TransportTaskStatusClient; import cn.code.nl.module.task.dal.dataobject.transporttask.TransportTaskDO; import cn.code.nl.module.task.dal.mysql.transporttask.TransportTaskMapper; import cn.code.nl.module.task.dto.AcsFeedbackReqDTO; -import cn.code.nl.module.task.mq.message.TaskEventMessage; +import cn.code.nl.module.task.message.TaskEventMessage; import cn.code.nl.module.task.dto.TaskStatusCallbackReqDTO; import cn.code.nl.module.task.dto.TaskStatusCallbackRespDTO; import cn.code.nl.module.task.enums.CallbackStatusEnum; diff --git a/docs/superpowers/plans/2026-07-15-task-operation-refactor.md b/docs/superpowers/plans/2026-07-15-task-operation-refactor.md index d2bf1e46..12cf48f7 100644 --- a/docs/superpowers/plans/2026-07-15-task-operation-refactor.md +++ b/docs/superpowers/plans/2026-07-15-task-operation-refactor.md @@ -202,7 +202,7 @@ import cn.code.nl.module.task.dto.AcsFeedbackReqDTO; import cn.code.nl.module.task.dto.TaskStatusCallbackReqDTO; import cn.code.nl.module.task.enums.TaskEventTypeEnum; import cn.code.nl.module.task.enums.TaskOperationTypeEnum; -import cn.code.nl.module.task.mq.message.TaskEventMessage; +import cn.code.nl.module.task.message.TaskEventMessage; import cn.code.nl.module.task.mq.producer.TaskEventProducer; import cn.hutool.core.util.StrUtil; import jakarta.annotation.PostConstruct; diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/mq/message/TaskEventMessage.java b/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/message/TaskEventMessage.java similarity index 94% rename from nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/mq/message/TaskEventMessage.java rename to nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/message/TaskEventMessage.java index 63ffe8a1..7cf0c26b 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/mq/message/TaskEventMessage.java +++ b/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/message/TaskEventMessage.java @@ -1,4 +1,4 @@ -package cn.code.nl.module.task.mq.message; +package cn.code.nl.module.task.message; import lombok.Data; diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskOperationManager.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskOperationManager.java index e0c3785f..bba4c42d 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskOperationManager.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskOperationManager.java @@ -9,7 +9,7 @@ import cn.code.nl.module.task.enums.FinishedTypeEnum; import cn.code.nl.module.task.enums.TaskEventTypeEnum; import cn.code.nl.module.task.enums.TaskOperationTypeEnum; import cn.code.nl.module.task.enums.TransportTaskStatusEnum; -import cn.code.nl.module.task.mq.message.TaskEventMessage; +import cn.code.nl.module.task.message.TaskEventMessage; import cn.code.nl.module.task.mq.producer.TaskEventProducer; import cn.hutool.core.util.StrUtil; import jakarta.annotation.PostConstruct; diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/mq/producer/TaskEventProducer.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/mq/producer/TaskEventProducer.java index 4168d271..2c5dae74 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/mq/producer/TaskEventProducer.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/mq/producer/TaskEventProducer.java @@ -1,6 +1,6 @@ package cn.code.nl.module.task.mq.producer; -import cn.code.nl.module.task.mq.message.TaskEventMessage; +import cn.code.nl.module.task.message.TaskEventMessage; import lombok.extern.slf4j.Slf4j; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.stereotype.Component; From 65fb53fc004c1c255dfa4a63b1343b205ab7a0e6 Mon Sep 17 00:00:00 2001 From: liyongde <1419499670@qq.com> Date: Thu, 23 Jul 2026 16:05:51 +0800 Subject: [PATCH 2/8] =?UTF-8?q?opt:=20=E6=8A=8A=20LMS/WMS=20=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E7=9A=84=E6=89=A7=E8=A1=8C=E9=80=BB=E8=BE=91=E4=B8=8B?= =?UTF-8?q?=E6=B2=89=E5=88=B0=20starter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../biz/api/AbstractTaskCommonApiImpl.java | 115 +++++++++++++ .../execute/biz/api/TaskCommonApi.java | 14 +- .../execute/biz/api/lms/LmsTaskCommonApi.java | 2 +- .../execute/biz/api/wms/WmsTaskCommonApi.java | 2 +- .../execute/biz/vo/AcsApplyActionRespVO.java | 3 +- .../execute/core/dto/TaskExecuteDTO.java | 6 + .../module/lms/api/LmsTaskExecuteApiImpl.java | 18 ++ .../cn/code/nl/module/lms/demo/DemoApi.java | 160 +++++++++--------- .../nl/module/lms/manage/package-info.java | 6 + ...TransportTaskBusinessOperationManager.java | 32 ++-- .../module/wms/api/WmsTaskExecuteApiImpl.java | 18 ++ 11 files changed, 266 insertions(+), 110 deletions(-) create mode 100644 nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/api/AbstractTaskCommonApiImpl.java create mode 100644 nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/api/LmsTaskExecuteApiImpl.java create mode 100644 nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/manage/package-info.java create mode 100644 nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/api/WmsTaskExecuteApiImpl.java diff --git a/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/api/AbstractTaskCommonApiImpl.java b/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/api/AbstractTaskCommonApiImpl.java new file mode 100644 index 00000000..9f4fb1e5 --- /dev/null +++ b/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/api/AbstractTaskCommonApiImpl.java @@ -0,0 +1,115 @@ +package cn.code.nl.framework.execute.biz.api; + +import cn.code.nl.framework.common.exception.ServiceException; +import cn.code.nl.framework.common.pojo.CommonResult; +import cn.code.nl.framework.execute.biz.dto.TaskStatusCallApiReqDTO; +import cn.code.nl.framework.execute.biz.vo.AcsApplyActionRespVO; +import cn.code.nl.framework.execute.core.AbstractTask; +import cn.code.nl.framework.execute.core.TaskFactory; +import cn.code.nl.framework.execute.core.dto.TaskExecuteDTO; +import jakarta.annotation.Resource; + +/** + * 任务通用 API 公共实现 + * + * @author liyongde + */ +public abstract class AbstractTaskCommonApiImpl implements TaskCommonApi { + + /** + * 任务处理器工厂 + */ + @Resource + private TaskFactory taskFactory; + + /** + * 处理取货完成 + */ + @Override + public CommonResult doHandlePicked(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { + return execute(taskStatusCallApiReqDTO, (task, taskExecuteDTO) -> { + task.doHandlePicked(taskExecuteDTO); + return null; + }); + } + + /** + * 处理二次请求 + */ + @Override + public CommonResult doHandleApplyAgain(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { + return execute(taskStatusCallApiReqDTO, AbstractTask::againApply); + } + + /** + * 处理请求放货 + */ + @Override + public CommonResult doHandleRequestRelease(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { + return execute(taskStatusCallApiReqDTO, AbstractTask::requestPutAway); + } + + /** + * 处理请求取货 + */ + @Override + public CommonResult doHandleRequestPick(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { + return execute(taskStatusCallApiReqDTO, AbstractTask::requestPickGoods); + } + + /** + * 处理请求离开 + */ + @Override + public CommonResult doHandleRequestLeave(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { + return execute(taskStatusCallApiReqDTO, AbstractTask::requestOut); + } + + /** + * 处理请求进入 + */ + @Override + public CommonResult doHandleRequestEnter(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { + return execute(taskStatusCallApiReqDTO, AbstractTask::requestIn); + } + + /** + * 根据 handleCode 路由到具体任务处理器 + */ + private CommonResult execute(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO, + TaskActionInvoker taskActionInvoker) { + AbstractTask task = taskFactory.getTask(taskStatusCallApiReqDTO.getHandleCode()); + if (task == null) { + throw new ServiceException(500, "未找到任务处理器:" + taskStatusCallApiReqDTO.getHandleCode()); + } + Object data = taskActionInvoker.invoke(task, buildTaskExecuteDTO(taskStatusCallApiReqDTO)); + + AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); + respVO.setTaskId(taskStatusCallApiReqDTO.getTaskId()); + respVO.setTaskCode(taskStatusCallApiReqDTO.getTaskCode()); + respVO.setData(data); + return CommonResult.success(respVO); + } + + /** + * 构建任务执行参数 + */ + private TaskExecuteDTO buildTaskExecuteDTO(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { + return TaskExecuteDTO.builder() + .taskId(taskStatusCallApiReqDTO.getTaskId()) + .payload(taskStatusCallApiReqDTO.getPayload()) + .build(); + } + + /** + * 任务动作调用器 + */ + @FunctionalInterface + private interface TaskActionInvoker { + + /** + * 调用任务动作 + */ + Object invoke(AbstractTask task, TaskExecuteDTO taskExecuteDTO); + } +} diff --git a/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/api/TaskCommonApi.java b/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/api/TaskCommonApi.java index 66d9a473..fff86e58 100644 --- a/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/api/TaskCommonApi.java +++ b/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/api/TaskCommonApi.java @@ -4,8 +4,8 @@ import cn.code.nl.framework.common.pojo.CommonResult; import cn.code.nl.framework.execute.biz.dto.TaskStatusCallApiReqDTO; import cn.code.nl.framework.execute.biz.vo.AcsApplyActionRespVO; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; /** * @@ -16,25 +16,25 @@ public interface TaskCommonApi { @Operation(summary = "请求取货") @PostMapping("/do-handle-picked") - CommonResult doHandlePicked(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO); + CommonResult doHandlePicked(@RequestBody TaskStatusCallApiReqDTO taskStatusCallApiReqDTO); @Operation(summary = "二次请求") @PostMapping("/do-handle-apply-again") - CommonResult doHandleApplyAgain(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO); + CommonResult doHandleApplyAgain(@RequestBody TaskStatusCallApiReqDTO taskStatusCallApiReqDTO); @Operation(summary = "处理请求放货") @PostMapping("/do-handle-request-release") - CommonResult doHandleRequestRelease(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO); + CommonResult doHandleRequestRelease(@RequestBody TaskStatusCallApiReqDTO taskStatusCallApiReqDTO); @Operation(summary = "处理请求取货") @PostMapping("/do-handle-request-pick") - CommonResult doHandleRequestPick(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO); + CommonResult doHandleRequestPick(@RequestBody TaskStatusCallApiReqDTO taskStatusCallApiReqDTO); @Operation(summary = "处理请求离开") @PostMapping("/do-handle-request-leave") - CommonResult doHandleRequestLeave(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO); + CommonResult doHandleRequestLeave(@RequestBody TaskStatusCallApiReqDTO taskStatusCallApiReqDTO); @Operation(summary = "处理请求进入") @PostMapping("/do-handle-request-enter") - CommonResult doHandleRequestEnter(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO); + CommonResult doHandleRequestEnter(@RequestBody TaskStatusCallApiReqDTO taskStatusCallApiReqDTO); } diff --git a/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/api/lms/LmsTaskCommonApi.java b/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/api/lms/LmsTaskCommonApi.java index 06c2efc1..ac559a20 100644 --- a/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/api/lms/LmsTaskCommonApi.java +++ b/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/api/lms/LmsTaskCommonApi.java @@ -11,7 +11,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; * @Author: liyongde * @Date: 2026/7/15 14:39 */ -@FeignClient(name = RpcConstants.LMS_NAME, path = "/lms", primary = false) // TODO 芋艿:fallbackFactory = +@FeignClient(name = RpcConstants.LMS_NAME, path = RpcConstants.RPC_API_PREFIX + "/lms", primary = false) // TODO 芋艿:fallbackFactory = @Tag(name = "RPC 服务 - lms任务") public interface LmsTaskCommonApi extends TaskCommonApi { } diff --git a/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/api/wms/WmsTaskCommonApi.java b/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/api/wms/WmsTaskCommonApi.java index dd2a83b3..d4977342 100644 --- a/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/api/wms/WmsTaskCommonApi.java +++ b/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/api/wms/WmsTaskCommonApi.java @@ -11,7 +11,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; * @Author: liyongde * @Date: 2026/7/15 14:48 */ -@FeignClient(name = RpcConstants.WMS_NAME, path = "/wms", primary = false) // TODO 芋艿:fallbackFactory = +@FeignClient(name = RpcConstants.WMS_NAME, path = RpcConstants.RPC_API_PREFIX + "/wms", primary = false) // TODO 芋艿:fallbackFactory = @Tag(name = "RPC 服务 - wms任务") public interface WmsTaskCommonApi extends TaskCommonApi { } diff --git a/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/vo/AcsApplyActionRespVO.java b/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/vo/AcsApplyActionRespVO.java index 5096efe6..2a395188 100644 --- a/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/vo/AcsApplyActionRespVO.java +++ b/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/biz/vo/AcsApplyActionRespVO.java @@ -1,6 +1,5 @@ package cn.code.nl.framework.execute.biz.vo; -import com.alibaba.fastjson.JSONObject; import lombok.Data; /** @@ -25,5 +24,5 @@ public class AcsApplyActionRespVO { /** * 数据 */ - private JSONObject data; + private Object data; } diff --git a/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/core/dto/TaskExecuteDTO.java b/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/core/dto/TaskExecuteDTO.java index dc07f545..e0cff2a4 100644 --- a/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/core/dto/TaskExecuteDTO.java +++ b/nl-framework/nl-spring-boot-starter-execute/src/main/java/cn/code/nl/framework/execute/core/dto/TaskExecuteDTO.java @@ -2,7 +2,10 @@ package cn.code.nl.framework.execute.core.dto; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import java.util.Map; @@ -12,6 +15,9 @@ import java.util.Map; * @Date: 2026/7/16 14:57 */ @Data +@Builder +@NoArgsConstructor +@AllArgsConstructor public class TaskExecuteDTO { @Schema(description = "任务id") diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/api/LmsTaskExecuteApiImpl.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/api/LmsTaskExecuteApiImpl.java new file mode 100644 index 00000000..fb0e9fe4 --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/api/LmsTaskExecuteApiImpl.java @@ -0,0 +1,18 @@ +package cn.code.nl.module.lms.api; + +import cn.code.nl.framework.execute.biz.api.AbstractTaskCommonApiImpl; +import cn.code.nl.framework.execute.biz.api.lms.LmsTaskCommonApi; +import org.springframework.context.annotation.Primary; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RestController; + +/** + * LMS 任务通用 API 实现 + * + * @author liyongde + */ +@RestController +@Validated +@Primary +public class LmsTaskExecuteApiImpl extends AbstractTaskCommonApiImpl implements LmsTaskCommonApi { +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/demo/DemoApi.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/demo/DemoApi.java index a1b44f70..b08f3ad9 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/demo/DemoApi.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/demo/DemoApi.java @@ -1,80 +1,80 @@ -package cn.code.nl.module.lms.demo; - -import cn.code.nl.framework.common.pojo.CommonResult; -import cn.code.nl.framework.execute.biz.api.lms.LmsTaskCommonApi; -import cn.code.nl.framework.execute.biz.dto.TaskStatusCallApiReqDTO; -import cn.code.nl.framework.execute.biz.vo.AcsApplyActionRespVO; -import com.alibaba.fastjson.JSON; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.RestController; - -import static cn.code.nl.framework.common.pojo.CommonResult.success; - -/** - * - * @Author: liyongde - * @Date: 2026/7/15 15:25 - */ -@RestController // 提供 RESTful API 接口,给 Feign 调用 -@Validated -public class DemoApi implements LmsTaskCommonApi { - @Override - public CommonResult doHandlePicked(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { - // 构建外层VO - AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); - respVO.setTaskId(10001L); - respVO.setTaskCode("ACS20260716001"); - // 内层data赋值 "success" - return success(respVO); - } - - @Override - public CommonResult doHandleApplyAgain(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { - DemoRespVO demoRespVO = new DemoRespVO(); - demoRespVO.setTargetPoint("A_10001"); - - // 构建外层VO - AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); - respVO.setTaskId(10001L); - respVO.setTaskCode("ACS20260716001"); - // 内层data赋值 "success" - respVO.setData(JSON.parseObject(JSON.toJSONString(demoRespVO))); - return success(respVO); - } - - @Override - public CommonResult doHandleRequestRelease(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { - // 构建外层VO - AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); - respVO.setTaskId(10001L); - respVO.setTaskCode("ACS20260716001"); - return success(respVO); - } - - @Override - public CommonResult doHandleRequestPick(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { - // 构建外层VO - AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); - respVO.setTaskId(10001L); - respVO.setTaskCode("ACS20260716001"); - return success(respVO); - } - - @Override - public CommonResult doHandleRequestLeave(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { - // 构建外层VO - AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); - respVO.setTaskId(10001L); - respVO.setTaskCode("ACS20260716001"); - return success(respVO); - } - - @Override - public CommonResult doHandleRequestEnter(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { - // 构建外层VO - AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); - respVO.setTaskId(10001L); - respVO.setTaskCode("ACS20260716001"); - return success(respVO); - } -} +//package cn.code.nl.module.lms.demo; +// +//import cn.code.nl.framework.common.pojo.CommonResult; +//import cn.code.nl.framework.execute.biz.api.lms.LmsTaskCommonApi; +//import cn.code.nl.framework.execute.biz.dto.TaskStatusCallApiReqDTO; +//import cn.code.nl.framework.execute.biz.vo.AcsApplyActionRespVO; +//import com.alibaba.fastjson.JSON; +//import org.springframework.validation.annotation.Validated; +//import org.springframework.web.bind.annotation.RestController; +// +//import static cn.code.nl.framework.common.pojo.CommonResult.success; +// +///** +// * +// * @Author: liyongde +// * @Date: 2026/7/15 15:25 +// */ +//@RestController // 提供 RESTful API 接口,给 Feign 调用 +//@Validated +//public class DemoApi implements LmsTaskCommonApi { +// @Override +// public CommonResult doHandlePicked(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { +// // 构建外层VO +// AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); +// respVO.setTaskId(10001L); +// respVO.setTaskCode("ACS20260716001"); +// // 内层data赋值 "success" +// return success(respVO); +// } +// +// @Override +// public CommonResult doHandleApplyAgain(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { +// DemoRespVO demoRespVO = new DemoRespVO(); +// demoRespVO.setTargetPoint("A_10001"); +// +// // 构建外层VO +// AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); +// respVO.setTaskId(10001L); +// respVO.setTaskCode("ACS20260716001"); +// // 内层data赋值 "success" +// respVO.setData(JSON.parseObject(JSON.toJSONString(demoRespVO))); +// return success(respVO); +// } +// +// @Override +// public CommonResult doHandleRequestRelease(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { +// // 构建外层VO +// AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); +// respVO.setTaskId(10001L); +// respVO.setTaskCode("ACS20260716001"); +// return success(respVO); +// } +// +// @Override +// public CommonResult doHandleRequestPick(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { +// // 构建外层VO +// AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); +// respVO.setTaskId(10001L); +// respVO.setTaskCode("ACS20260716001"); +// return success(respVO); +// } +// +// @Override +// public CommonResult doHandleRequestLeave(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { +// // 构建外层VO +// AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); +// respVO.setTaskId(10001L); +// respVO.setTaskCode("ACS20260716001"); +// return success(respVO); +// } +// +// @Override +// public CommonResult doHandleRequestEnter(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { +// // 构建外层VO +// AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); +// respVO.setTaskId(10001L); +// respVO.setTaskCode("ACS20260716001"); +// return success(respVO); +// } +//} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/manage/package-info.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/manage/package-info.java new file mode 100644 index 00000000..9e091556 --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/manage/package-info.java @@ -0,0 +1,6 @@ +/** + * + * @Author: liyongde + * @Date: 2026/7/23 14:41 + */ +package cn.code.nl.module.lms.manage; \ No newline at end of file diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskBusinessOperationManager.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskBusinessOperationManager.java index 1d24db11..7c492c2c 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskBusinessOperationManager.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskBusinessOperationManager.java @@ -11,7 +11,6 @@ import cn.code.nl.module.task.dal.mysql.transporttask.TransportTaskMapper; import cn.code.nl.module.task.dto.AcsFeedbackReqDTO; import cn.code.nl.module.task.enums.AcsBusinessOperationTypeEnum; import cn.code.nl.module.task.enums.TransportTaskStatusEnum; -import com.alibaba.fastjson.JSON; import jakarta.annotation.PostConstruct; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -104,68 +103,63 @@ public class TransportTaskBusinessOperationManager { TaskCommonApi serverApi = taskCommonApiFactory.getByServerName(task.getOwnerService()); CommonResult result = serverApi.doHandlePicked(buildReq(task, reqDTO)); - return result.getData(); + return result.getCheckedData(); } /** * 处理二次请求 */ private AcsApplyActionRespVO handleApplyAgain(TransportTaskDO task, AcsFeedbackReqDTO reqDTO) { - // TODO 二次请求业务待开发 - log.info("二次请求业务待开发, taskId={}", task.getTaskId()); + log.info("二次请求, taskId={}", task.getTaskId()); // 调用具体的服务去执行取货完成操作。 TaskCommonApi serverApi = taskCommonApiFactory.getByServerName(task.getOwnerService()); CommonResult result = serverApi.doHandleApplyAgain(buildReq(task, reqDTO)); - return result.getData(); + return result.getCheckedData(); } /** * 处理请求放货 */ private Object handleRequestRelease(TransportTaskDO task, AcsFeedbackReqDTO reqDTO) { - // TODO 请求放货业务待开发 - log.info("请求放货业务待开发, taskId={}", task.getTaskId()); + log.info("请求放货, taskId={}", task.getTaskId()); TaskCommonApi serverApi = taskCommonApiFactory.getByServerName(task.getOwnerService()); CommonResult result = serverApi.doHandleRequestRelease(buildReq(task, reqDTO)); - return result.getData(); + return result.getCheckedData(); } /** * 处理请求取货 */ private Object handleRequestPick(TransportTaskDO task, AcsFeedbackReqDTO reqDTO) { - // TODO 请求取货业务待开发 - log.info("请求取货业务待开发, taskId={}", task.getTaskId()); + log.info("请求取货, taskId={}", task.getTaskId()); TaskCommonApi serverApi = taskCommonApiFactory.getByServerName(task.getOwnerService()); CommonResult result = serverApi.doHandleRequestPick(buildReq(task, reqDTO)); - return result.getData(); + return result.getCheckedData(); } /** * 处理请求离开 */ private Object handleRequestLeave(TransportTaskDO task, AcsFeedbackReqDTO reqDTO) { - // TODO 请求离开业务待开发 - log.info("请求离开业务待开发, taskId={}", task.getTaskId()); + log.info("请求离开, taskId={}", task.getTaskId()); TaskCommonApi serverApi = taskCommonApiFactory.getByServerName(task.getOwnerService()); CommonResult result = serverApi.doHandleRequestLeave(buildReq(task, reqDTO)); - return result.getData(); + return result.getCheckedData(); } /** * 处理请求进入 */ private Object handleRequestEnter(TransportTaskDO task, AcsFeedbackReqDTO reqDTO) { - // TODO 请求进入业务待开发 - log.info("请求进入业务待开发, taskId={}", task.getTaskId()); + log.info("请求进入, taskId={}", task.getTaskId()); TaskCommonApi serverApi = taskCommonApiFactory.getByServerName(task.getOwnerService()); CommonResult result = serverApi.doHandleRequestEnter(buildReq(task, reqDTO)); - return result.getData(); + return result.getCheckedData(); } /** @@ -175,7 +169,7 @@ public class TransportTaskBusinessOperationManager { AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); respVO.setTaskId(task.getTaskId()); respVO.setTaskCode(task.getTaskCode()); - respVO.setData(JSON.parseObject(JSON.toJSONString(data))); + respVO.setData(data); return respVO; } /** @@ -185,7 +179,7 @@ public class TransportTaskBusinessOperationManager { TaskStatusCallApiReqDTO req = new TaskStatusCallApiReqDTO(); req.setTaskId(task.getTaskId()); req.setTaskCode(task.getTaskCode()); - req.setStatus(TransportTaskStatusEnum.PICKED.getCode()); + req.setStatus(reqDTO.getStatus()); req.setOwnerService(task.getOwnerService()); req.setBizType(task.getBizType()); req.setBizId(task.getBizId()); diff --git a/nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/api/WmsTaskExecuteApiImpl.java b/nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/api/WmsTaskExecuteApiImpl.java new file mode 100644 index 00000000..33a7fc44 --- /dev/null +++ b/nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/api/WmsTaskExecuteApiImpl.java @@ -0,0 +1,18 @@ +package cn.code.nl.module.wms.api; + +import cn.code.nl.framework.execute.biz.api.AbstractTaskCommonApiImpl; +import cn.code.nl.framework.execute.biz.api.wms.WmsTaskCommonApi; +import org.springframework.context.annotation.Primary; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RestController; + +/** + * WMS 任务通用 API 实现 + * + * @author liyongde + */ +@RestController +@Validated +@Primary +public class WmsTaskExecuteApiImpl extends AbstractTaskCommonApiImpl implements WmsTaskCommonApi { +} From 6f566b7a694e7ff7d3efa1780947e710bfa611b7 Mon Sep 17 00:00:00 2001 From: liyongde <1419499670@qq.com> Date: Thu, 23 Jul 2026 16:48:05 +0800 Subject: [PATCH 3/8] =?UTF-8?q?opt:=20=E4=BB=BB=E5=8A=A1=E5=8F=91=E9=80=81?= =?UTF-8?q?=E6=B6=88=E8=B4=B9=E8=80=85topic=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nl-module-lms/nl-module-lms-server/pom.xml | 6 +- .../cn/code/nl/module/lms/demo/DemoApi.java | 80 ------------------- .../consumer/LmsTaskStatusChangeConsumer.java | 54 +++++++++++++ .../code/nl/module/lms/mq/package-info.java | 6 ++ .../main/resources/application-mq-dev.yaml | 11 +++ .../src/main/resources/application.yaml | 1 + .../task/mq/producer/TaskEventProducer.java | 8 +- .../src/main/resources/application-dev.yaml | 7 +- ....java => WmsTaskStatusChangeConsumer.java} | 2 +- .../main/resources/application-mq-dev.yaml | 3 + .../main/resources/application-mq-dev.yaml | 3 + 11 files changed, 94 insertions(+), 87 deletions(-) delete mode 100644 nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/demo/DemoApi.java create mode 100644 nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/mq/consumer/LmsTaskStatusChangeConsumer.java create mode 100644 nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/mq/package-info.java create mode 100644 nl-module-lms/nl-module-lms-server/src/main/resources/application-mq-dev.yaml rename nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/mq/consumer/{TaskStatusChangeConsumer.java => WmsTaskStatusChangeConsumer.java} (95%) diff --git a/nl-module-lms/nl-module-lms-server/pom.xml b/nl-module-lms/nl-module-lms-server/pom.xml index 562d3f5f..b415622a 100644 --- a/nl-module-lms/nl-module-lms-server/pom.xml +++ b/nl-module-lms/nl-module-lms-server/pom.xml @@ -32,7 +32,11 @@ nl-module-lms-api ${revision} - + + cn.nl.cloud + nl-module-task-api + ${revision} + cn.nl.cloud diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/demo/DemoApi.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/demo/DemoApi.java deleted file mode 100644 index b08f3ad9..00000000 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/demo/DemoApi.java +++ /dev/null @@ -1,80 +0,0 @@ -//package cn.code.nl.module.lms.demo; -// -//import cn.code.nl.framework.common.pojo.CommonResult; -//import cn.code.nl.framework.execute.biz.api.lms.LmsTaskCommonApi; -//import cn.code.nl.framework.execute.biz.dto.TaskStatusCallApiReqDTO; -//import cn.code.nl.framework.execute.biz.vo.AcsApplyActionRespVO; -//import com.alibaba.fastjson.JSON; -//import org.springframework.validation.annotation.Validated; -//import org.springframework.web.bind.annotation.RestController; -// -//import static cn.code.nl.framework.common.pojo.CommonResult.success; -// -///** -// * -// * @Author: liyongde -// * @Date: 2026/7/15 15:25 -// */ -//@RestController // 提供 RESTful API 接口,给 Feign 调用 -//@Validated -//public class DemoApi implements LmsTaskCommonApi { -// @Override -// public CommonResult doHandlePicked(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { -// // 构建外层VO -// AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); -// respVO.setTaskId(10001L); -// respVO.setTaskCode("ACS20260716001"); -// // 内层data赋值 "success" -// return success(respVO); -// } -// -// @Override -// public CommonResult doHandleApplyAgain(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { -// DemoRespVO demoRespVO = new DemoRespVO(); -// demoRespVO.setTargetPoint("A_10001"); -// -// // 构建外层VO -// AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); -// respVO.setTaskId(10001L); -// respVO.setTaskCode("ACS20260716001"); -// // 内层data赋值 "success" -// respVO.setData(JSON.parseObject(JSON.toJSONString(demoRespVO))); -// return success(respVO); -// } -// -// @Override -// public CommonResult doHandleRequestRelease(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { -// // 构建外层VO -// AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); -// respVO.setTaskId(10001L); -// respVO.setTaskCode("ACS20260716001"); -// return success(respVO); -// } -// -// @Override -// public CommonResult doHandleRequestPick(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { -// // 构建外层VO -// AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); -// respVO.setTaskId(10001L); -// respVO.setTaskCode("ACS20260716001"); -// return success(respVO); -// } -// -// @Override -// public CommonResult doHandleRequestLeave(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { -// // 构建外层VO -// AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); -// respVO.setTaskId(10001L); -// respVO.setTaskCode("ACS20260716001"); -// return success(respVO); -// } -// -// @Override -// public CommonResult doHandleRequestEnter(TaskStatusCallApiReqDTO taskStatusCallApiReqDTO) { -// // 构建外层VO -// AcsApplyActionRespVO respVO = new AcsApplyActionRespVO(); -// respVO.setTaskId(10001L); -// respVO.setTaskCode("ACS20260716001"); -// return success(respVO); -// } -//} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/mq/consumer/LmsTaskStatusChangeConsumer.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/mq/consumer/LmsTaskStatusChangeConsumer.java new file mode 100644 index 00000000..58a38267 --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/mq/consumer/LmsTaskStatusChangeConsumer.java @@ -0,0 +1,54 @@ +package cn.code.nl.module.lms.mq.consumer; + +import cn.code.nl.framework.execute.core.AbstractTask; +import cn.code.nl.framework.execute.core.TaskFactory; +import cn.code.nl.framework.execute.core.dto.TaskExecuteDTO; +import cn.code.nl.module.task.message.TaskEventMessage; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.stereotype.Component; + +/** + * 监听任务状态变更,根据 handleCode 定位任务子类并执行完成/取消逻辑 + * + * @Author: liyongde + * @Date: 2026/7/20 10:28 + */ +@Slf4j +@Component +@RocketMQMessageListener( + topic = "${rocketmq.consumer.lms-task-operate.topic}", + consumerGroup = "${rocketmq.consumer.lms-task-operate.group}" +) +public class LmsTaskStatusChangeConsumer implements RocketMQListener { + + @Resource + private TaskFactory taskFactory; + + @Override + public void onMessage(TaskEventMessage message) { + String handleCode = message.getHandleCode(); + String eventType = message.getEventType(); + log.info("收到任务状态变更消息, handleCode={}, eventType={}, taskId={}", handleCode, eventType, message.getTaskId()); + + AbstractTask task = taskFactory.getTask(handleCode); + if (task == null) { + log.warn("未找到对应任务处理器, handleCode={}", handleCode); + return; + } + + TaskExecuteDTO dto = new TaskExecuteDTO(); + dto.setTaskId(message.getTaskId()); + dto.setPayload(message.getPayload()); + + if (TaskEventMessage.EVENT_TYPE_FINISHED.equals(eventType)) { + task.doHandleFinish(dto); + } else if (TaskEventMessage.EVENT_TYPE_CANCELLED.equals(eventType)) { + task.doHandleCancel(dto); + } else { + log.warn("未知事件类型, eventType={}, handleCode={}", eventType, handleCode); + } + } +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/mq/package-info.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/mq/package-info.java new file mode 100644 index 00000000..dfa0616a --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/mq/package-info.java @@ -0,0 +1,6 @@ +/** + * + * @Author: liyongde + * @Date: 2026/7/23 16:21 + */ +package cn.code.nl.module.lms.mq; \ No newline at end of file diff --git a/nl-module-lms/nl-module-lms-server/src/main/resources/application-mq-dev.yaml b/nl-module-lms/nl-module-lms-server/src/main/resources/application-mq-dev.yaml new file mode 100644 index 00000000..3fab2cc8 --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/resources/application-mq-dev.yaml @@ -0,0 +1,11 @@ +--- #################### MQ 消息队列相关配置 #################### +# rocketmq 配置项,对应 RocketMQProperties 配置类 +rocketmq: + name-server: 192.168.81.193:9876 + producer: + group: lms-producer-dev-group # 事务消息需要配置一样 + send-message-timeout: 3000 + consumer: + lms-task-operate: + group: lms-task-status-change-dev-group + topic: lms-task-status-change-dev-topic \ No newline at end of file diff --git a/nl-module-lms/nl-module-lms-server/src/main/resources/application.yaml b/nl-module-lms/nl-module-lms-server/src/main/resources/application.yaml index aa71aa8b..d811bc01 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/resources/application.yaml +++ b/nl-module-lms/nl-module-lms-server/src/main/resources/application.yaml @@ -13,6 +13,7 @@ spring: import: - optional:classpath:application-${spring.profiles.active}.yaml # 加载【本地】配置 - optional:nacos:${spring.application.name}-${spring.profiles.active}.yaml # 加载【Nacos】的配置 + - optional:classpath:application-mq-${spring.profiles.active}.yaml # 加载 MQ 配置 # Servlet 配置 servlet: diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/mq/producer/TaskEventProducer.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/mq/producer/TaskEventProducer.java index 2c5dae74..77f232d6 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/mq/producer/TaskEventProducer.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/mq/producer/TaskEventProducer.java @@ -6,19 +6,21 @@ import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.stereotype.Component; import jakarta.annotation.Resource; +import org.springframework.beans.factory.annotation.Value; import java.util.UUID; /** * 任务事件 MQ 生产者 *

- * Topic: TASK_EVENT_TOPIC + * Topic 从 YAML 配置 rocketmq.consumer.task.topic 读取 * Tag: ownerService (LMS / WMS) */ @Slf4j @Component public class TaskEventProducer { - private static final String TOPIC = "TASK_EVENT_TOPIC"; + @Value("${rocketmq.consumer.task.topic}") + private String topic; @Resource private RocketMQTemplate rocketMQTemplate; @@ -34,7 +36,7 @@ public class TaskEventProducer { message.setEventId(UUID.randomUUID().toString()); } - String destination = TOPIC + "_" + message.getOwnerService(); + String destination = message.getOwnerService() + "_" + topic; try { rocketMQTemplate.syncSend(destination, message); log.info("MQ 发送成功, destination={}, taskId={}, eventType={}", diff --git a/nl-module-task/nl-module-task-server/src/main/resources/application-dev.yaml b/nl-module-task/nl-module-task-server/src/main/resources/application-dev.yaml index faf8d89f..49d41b9c 100644 --- a/nl-module-task/nl-module-task-server/src/main/resources/application-dev.yaml +++ b/nl-module-task/nl-module-task-server/src/main/resources/application-dev.yaml @@ -78,9 +78,12 @@ spring: # rocketmq 配置项,对应 RocketMQProperties 配置类 rocketmq: - name-server: 127.0.0.1:9876 # RocketMQ Namesrv + name-server: 192.168.81.193:9876 # RocketMQ Namesrv producer: - group: ${spring.application.name}_TASK_DEV_PRODUCER # 生产者分组 + group: task-producer-dev-group # 生产者分组 + consumer: + task: + topic: task-status-change-dev-topic spring: # RabbitMQ 配置项,对应 RabbitProperties 配置类 diff --git a/nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/mq/consumer/TaskStatusChangeConsumer.java b/nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/mq/consumer/WmsTaskStatusChangeConsumer.java similarity index 95% rename from nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/mq/consumer/TaskStatusChangeConsumer.java rename to nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/mq/consumer/WmsTaskStatusChangeConsumer.java index 57cbb940..fd51edee 100644 --- a/nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/mq/consumer/TaskStatusChangeConsumer.java +++ b/nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/mq/consumer/WmsTaskStatusChangeConsumer.java @@ -22,7 +22,7 @@ import org.springframework.stereotype.Component; topic = "${rocketmq.consumer.wms-task-operate.topic}", consumerGroup = "${rocketmq.consumer.wms-task-operate.group}" ) -public class TaskStatusChangeConsumer implements RocketMQListener { +public class WmsTaskStatusChangeConsumer implements RocketMQListener { @Resource private TaskFactory taskFactory; diff --git a/nl-module-wms/nl-module-wms-server/src/main/resources/application-mq-dev.yaml b/nl-module-wms/nl-module-wms-server/src/main/resources/application-mq-dev.yaml index b0a11c37..325cbd30 100644 --- a/nl-module-wms/nl-module-wms-server/src/main/resources/application-mq-dev.yaml +++ b/nl-module-wms/nl-module-wms-server/src/main/resources/application-mq-dev.yaml @@ -2,6 +2,9 @@ # rocketmq 配置项,对应 RocketMQProperties 配置类 rocketmq: name-server: 192.168.81.193:9876 + producer: + group: wms-producer-dev-group # 事务消息需要配置一样 + send-message-timeout: 3000 consumer: wms-task-operate: group: wms-task-status-change-dev-group diff --git a/nl-server/src/main/resources/application-mq-dev.yaml b/nl-server/src/main/resources/application-mq-dev.yaml index b0a11c37..72ed6218 100644 --- a/nl-server/src/main/resources/application-mq-dev.yaml +++ b/nl-server/src/main/resources/application-mq-dev.yaml @@ -2,6 +2,9 @@ # rocketmq 配置项,对应 RocketMQProperties 配置类 rocketmq: name-server: 192.168.81.193:9876 + producer: + group: nl-producer-dev-group + send-message-timeout: 3000 consumer: wms-task-operate: group: wms-task-status-change-dev-group From 89c21e900e3d661989c97cfb8de667745480e6a6 Mon Sep 17 00:00:00 2001 From: liyongde <1419499670@qq.com> Date: Fri, 24 Jul 2026 10:06:35 +0800 Subject: [PATCH 4/8] =?UTF-8?q?feat=EF=BC=9A=E4=BB=BB=E5=8A=A1=E5=AE=9A?= =?UTF-8?q?=E6=97=B6=E4=BB=BB=E5=8A=A1=E4=B8=8B=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/common/util/http/AcsUtil.java | 45 +++ .../module/lms/api/LmsTaskExecuteApiImpl.java | 3 + .../transporttask/TransportTaskDO.java | 340 +++++++++--------- .../transporttask/TransportTaskMapper.java | 25 +- .../nl/module/task/job/TaskScheduleJob.java | 14 +- .../nl/module/task/job/dto/AcsBaseReqDTO.java | 22 ++ .../task/job/dto/AcsIssueResultDTO.java | 51 +++ .../nl/module/task/job/dto/AcsTaskDTO.java | 71 ++++ .../manage/TransportTaskIssueManager.java | 138 +++++++ .../transporttask/TransportTaskService.java | 5 + .../TransportTaskServiceImpl.java | 58 +-- .../nl/module/task/utils/AcsTaskUtil.java | 41 +++ .../nl/module/task/utils/package-info.java | 6 + .../module/wms/api/WmsTaskExecuteApiImpl.java | 3 + 14 files changed, 623 insertions(+), 199 deletions(-) create mode 100644 nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/util/http/AcsUtil.java create mode 100644 nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsBaseReqDTO.java create mode 100644 nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsIssueResultDTO.java create mode 100644 nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsTaskDTO.java create mode 100644 nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskIssueManager.java create mode 100644 nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/utils/AcsTaskUtil.java create mode 100644 nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/utils/package-info.java diff --git a/nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/util/http/AcsUtil.java b/nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/util/http/AcsUtil.java new file mode 100644 index 00000000..9bf9806c --- /dev/null +++ b/nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/util/http/AcsUtil.java @@ -0,0 +1,45 @@ +package cn.code.nl.framework.common.util.http; + +import cn.code.nl.framework.common.util.json.JsonUtils; +import cn.hutool.core.util.StrUtil; + +import java.util.Collections; +import java.util.Map; + +/** + * ACS 调用工具 + */ +public class AcsUtil { + + /** + * 发送 POST 请求并解析响应 + * + * @param serverAddress ACS 服务地址 + * @param api API 路径 + * @param request 请求参数 + * @param responseType 响应类型 + * @return 响应对象 + */ + public static T post(String serverAddress, String api, Object request, Class responseType) { + String url = buildUrl(serverAddress, api); + String response = HttpUtils.post(url, headers(), JsonUtils.toJsonString(request)); + return JsonUtils.parseObject(response, responseType); + } + + /** + * 拼接服务地址和 API + */ + private static String buildUrl(String serverAddress, String api) { + String baseUrl = StrUtil.removeSuffix(serverAddress, StrUtil.SLASH); + String apiPath = StrUtil.addPrefixIfNot(api, StrUtil.SLASH); + return baseUrl + apiPath; + } + + /** + * 构建 JSON 请求头 + */ + private static Map headers() { + return Collections.singletonMap("Content-Type", "application/json;charset=UTF-8"); + } + +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/api/LmsTaskExecuteApiImpl.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/api/LmsTaskExecuteApiImpl.java index fb0e9fe4..994681d3 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/api/LmsTaskExecuteApiImpl.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/api/LmsTaskExecuteApiImpl.java @@ -1,9 +1,11 @@ package cn.code.nl.module.lms.api; +import cn.code.nl.framework.common.enums.RpcConstants; import cn.code.nl.framework.execute.biz.api.AbstractTaskCommonApiImpl; import cn.code.nl.framework.execute.biz.api.lms.LmsTaskCommonApi; import org.springframework.context.annotation.Primary; import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** @@ -14,5 +16,6 @@ import org.springframework.web.bind.annotation.RestController; @RestController @Validated @Primary +@RequestMapping(RpcConstants.LMS_PREFIX) public class LmsTaskExecuteApiImpl extends AbstractTaskCommonApiImpl implements LmsTaskCommonApi { } diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/dal/dataobject/transporttask/TransportTaskDO.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/dal/dataobject/transporttask/TransportTaskDO.java index 687fbc6c..1c4c393d 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/dal/dataobject/transporttask/TransportTaskDO.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/dal/dataobject/transporttask/TransportTaskDO.java @@ -1,170 +1,170 @@ -package cn.code.nl.module.task.dal.dataobject.transporttask; - -import lombok.*; -import java.util.*; -import java.time.LocalDateTime; -import java.time.LocalDateTime; -import com.baomidou.mybatisplus.annotation.*; -import cn.code.nl.framework.mybatis.core.dataobject.BaseDO; - -/** - * 搬运任务 DO - * - * @author 诺力管理员 - */ -@TableName("task_transport_job") -@KeySequence("task_transport_job_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class TransportTaskDO extends BaseDO { - - /** - * 任务标识 - */ - @TableId - private Long taskId; - /** - * 任务编码 - */ - private String taskCode; - /** - * 任务名称 - */ - private String taskName; - /** - * 业务归属服务:LMS/WMS,用于完成取消事件一级路由 - */ - private String ownerService; - /** - * 业务类型 - */ - private String bizType; - /** - * 业务侧标识 - */ - private String bizId; - /** - * 业务回调处理器编码 - */ - private String handleCode; - /** - * 任务类型 - */ - private String taskType; - /** - * 任务状态 - */ - private String taskStatus; - /** - * ACS任务类型 - */ - private String acsTaskType; - /** - * AGV系统类型 - */ - private String agvSystemType; - /** - * ACS外部任务号 - */ - private String externalTaskNo; - /** - * 取货点1 - */ - private String pointCode1; - /** - * 放货点1 - */ - private String pointCode2; - /** - * 取货点2 - */ - private String pointCode3; - /** - * 放货点2 - */ - private String pointCode4; - /** - * 载具类型 - */ - private String vehicleType; - /** - * 载具数量 - */ - private Long vehicleQty; - /** - * 载具编码 - */ - private String vehicleCode; - /** - * 载具编码2 - */ - private String vehicleCode2; - /** - * 车号 - */ - private String carNo; - /** - * 优先级 - */ - private String priority; - /** - * 生产区域 - */ - private String productArea; - /** - * 是否自动下发 - */ - private String isAutoIssue; - /** - * 任务组标识 - */ - private Long taskGroupId; - /** - * 任务组顺序号 - */ - private Long sortSeq; - /** - * 任务完成类型 - */ - private String finishedType; - /** - * 业务回调状态:PENDING/SUCCESS/FAILED - */ - private String callbackStatus; - /** - * 业务回调重试次数 - */ - private Integer callbackRetryCount; - /** - * 业务回调失败原因 - */ - private String callbackErrorMsg; - /** - * 生成方式 - * - * 枚举 {@link TODO user_type 对应的类} - */ - private String createMode; - /** - * 创建任务请求参数 - */ - private String requestParam; - /** - * 下发ACS的AcsTaskDto扩展报文 - */ - private String dispatchParam; - /** - * ACS反馈参数 - */ - private String resultParam; - /** - * 备注 - */ - private String remark; - - -} \ No newline at end of file +package cn.code.nl.module.task.dal.dataobject.transporttask; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.code.nl.framework.mybatis.core.dataobject.BaseDO; + +/** + * 搬运任务 DO + * + * @author 诺力管理员 + */ +@TableName("task_transport_job") +@KeySequence("task_transport_job_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TransportTaskDO extends BaseDO { + + /** + * 任务标识 + */ + @TableId + private Long taskId; + /** + * 任务编码 + */ + private String taskCode; + /** + * 任务名称 + */ + private String taskName; + /** + * 业务归属服务:LMS/WMS,用于完成取消事件一级路由 + */ + private String ownerService; + /** + * 业务类型 + */ + private String bizType; + /** + * 业务侧标识 + */ + private String bizId; + /** + * 业务回调处理器编码 + */ + private String handleCode; + /** + * 任务类型 + */ + private String taskType; + /** + * 任务状态 + */ + private String taskStatus; + /** + * ACS任务类型 + */ + private String acsTaskType; + /** + * AGV系统类型 + */ + private String agvSystemType; + /** + * ACS外部任务号 + */ + private String externalTaskNo; + /** + * 取货点1 + */ + private String pointCode1; + /** + * 放货点1 + */ + private String pointCode2; + /** + * 取货点2 + */ + private String pointCode3; + /** + * 放货点2 + */ + private String pointCode4; + /** + * 载具类型 + */ + private String vehicleType; + /** + * 载具数量 + */ + private Long vehicleQty; + /** + * 载具编码 + */ + private String vehicleCode; + /** + * 载具编码2 + */ + private String vehicleCode2; + /** + * 车号 + */ + private String carNo; + /** + * 优先级 + */ + private String priority; + /** + * 生产区域 + */ + private String productArea; + /** + * 是否自动下发 + */ + private String isAutoIssue; + /** + * 任务组标识 + */ + private Long taskGroupId; + /** + * 任务组顺序号 + */ + private Long sortSeq; + /** + * 任务完成类型 + */ + private String finishedType; + /** + * 业务回调状态:PENDING/SUCCESS/FAILED + */ + private String callbackStatus; + /** + * 业务回调重试次数 + */ + private Integer callbackRetryCount; + /** + * 业务回调失败原因 + */ + private String callbackErrorMsg; + /** + * 生成方式 + * + * 枚举 + */ + private String createMode; + /** + * 创建任务请求参数 + */ + private String requestParam; + /** + * 下发ACS的AcsTaskDto扩展报文 + */ + private String dispatchParam; + /** + * ACS反馈参数 + */ + private String resultParam; + /** + * 备注 + */ + private String remark; + + +} diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/dal/mysql/transporttask/TransportTaskMapper.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/dal/mysql/transporttask/TransportTaskMapper.java index 8acdbfac..5e52125a 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/dal/mysql/transporttask/TransportTaskMapper.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/dal/mysql/transporttask/TransportTaskMapper.java @@ -66,6 +66,17 @@ public interface TransportTaskMapper extends BaseMapperX { return selectOne(TransportTaskDO::getTaskCode, taskCode); } + /** + * 查询自动下发的待下发任务 + */ + default List selectAutoIssueReadyList() { + return selectList(new LambdaQueryWrapperX() + .eq(TransportTaskDO::getIsAutoIssue, "1") + .eq(TransportTaskDO::getTaskStatus, TransportTaskStatusEnum.READY.getCode()) + .orderByDesc(TransportTaskDO::getPriority) + .orderByAsc(TransportTaskDO::getTaskId)); + } + /** * 按业务归属查询未完结任务(幂等校验用) */ @@ -87,4 +98,16 @@ public interface TransportTaskMapper extends BaseMapperX { return update(null, wrapper) > 0; } -} \ No newline at end of file + /** + * 更新下发结果 + */ + default void updateIssueResult(Long taskId, String taskStatus, String resultParam, String remark) { + TransportTaskDO updateObj = new TransportTaskDO(); + updateObj.setTaskId(taskId); + updateObj.setTaskStatus(taskStatus); + updateObj.setResultParam(resultParam); + updateObj.setRemark(remark); + updateById(updateObj); + } + +} diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/TaskScheduleJob.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/TaskScheduleJob.java index 3fc005da..40540120 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/TaskScheduleJob.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/TaskScheduleJob.java @@ -1,28 +1,38 @@ package cn.code.nl.module.task.job; import cn.code.nl.framework.tenant.core.job.TenantJob; +import cn.code.nl.module.task.service.transporttask.TransportTaskService; import com.xxl.job.core.context.XxlJobHelper; import com.xxl.job.core.handler.annotation.XxlJob; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; /** * 任务相关的定时任务 + * * @Author: liyongde * @Date: 2026/7/13 14:01 */ +@Slf4j @Component public class TaskScheduleJob { + @Resource + private TransportTaskService transportTaskService; + @XxlJob("autoTaskAssignmentJob") @TenantJob public void autoTaskAssignmentJob() { + log.info("自动下发任务开始....."); XxlJobHelper.log("自动下发任务开始"); - // todo: 具体业务 + transportTaskService.autoIssueTransportTasks(); - String msg = "自动下发任务成功"; + String msg = "自动下发任务结束"; XxlJobHelper.log(msg); XxlJobHelper.handleSuccess(msg); + log.info(msg); } } diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsBaseReqDTO.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsBaseReqDTO.java new file mode 100644 index 00000000..a920d0c8 --- /dev/null +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsBaseReqDTO.java @@ -0,0 +1,22 @@ +package cn.code.nl.module.task.job.dto; + +import lombok.Data; + +/** + * 基础DTO对象 + * @Author: liyongde + * @Date: 2026/7/24 8:49 + */ +@Data +public class AcsBaseReqDTO { + /** + * 请求号: traceId + */ + private String traceId; + + /** + * + * 时间 + */ + private Long timestamp; +} diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsIssueResultDTO.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsIssueResultDTO.java new file mode 100644 index 00000000..b8bd4422 --- /dev/null +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsIssueResultDTO.java @@ -0,0 +1,51 @@ +package cn.code.nl.module.task.job.dto; + +import lombok.Data; + +import java.util.List; + +/** + * ACS 任务下发响应 + */ +@Data +public class AcsIssueResultDTO { + + /** + * 是否整体成功 + */ + private Boolean success; + + /** + * 响应编码 + */ + private String code; + + /** + * 响应消息 + */ + private String msg; + + /** + * 下发失败的任务 + */ + private List failedTasks; + + /** + * ACS 失败任务明细 + */ + @Data + public static class FailedTask { + + /** + * 任务标识 + */ + private Long taskId; + + /** + * 错误信息 + */ + private String errorMessage; + + } + +} diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsTaskDTO.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsTaskDTO.java new file mode 100644 index 00000000..0c3a2153 --- /dev/null +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsTaskDTO.java @@ -0,0 +1,71 @@ +package cn.code.nl.module.task.job.dto; + +import lombok.Data; + +import java.util.Map; + +/** + * 下发给ACS的实体 + * @Author: liyongde + * @Date: 2026/7/23 17:10 + */ +@Data +public class AcsTaskDTO extends AcsBaseReqDTO{ + /** + * 任务标识 + */ + private Long taskId; + /** + * 任务编码 + */ + private String taskCode; + /** + * 取货点1 + */ + private String startDeviceCode; + /** + * 放货点1 + */ + private String nextDeviceCode; + /** + * 取货点2 + */ + private String startDeviceCode2; + /** + * 放货点2 + */ + private String nextDeviceCode2; + /** + * 优先级 + */ + private String priority; + /** + * 载具号 + */ + private String vehicleCode; + /** + * 载具号2 + */ + private String vehicleCode2; + /** + * 任务类型 + */ + private String taskType; + /** + * Agv系统类型 + */ + private String agvSystemType; + + /** + * 备注 + */ + private String remark; + /** + * 扩展参数 + */ + private Map payload; + /** + * 生产区域 + */ + private String productArea; +} diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskIssueManager.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskIssueManager.java new file mode 100644 index 00000000..4224dd45 --- /dev/null +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskIssueManager.java @@ -0,0 +1,138 @@ +package cn.code.nl.module.task.manage; + +import cn.code.nl.framework.common.exception.ServiceException; +import cn.code.nl.framework.common.pojo.CommonResult; +import cn.code.nl.framework.common.util.http.AcsUtil; +import cn.code.nl.framework.common.util.json.JsonUtils; +import cn.code.nl.module.infra.api.config.ConfigApi; +import cn.code.nl.module.task.dal.dataobject.transporttask.TransportTaskDO; +import cn.code.nl.module.task.dal.mysql.transporttask.TransportTaskMapper; +import cn.code.nl.module.task.enums.TransportTaskStatusEnum; +import cn.code.nl.module.task.job.dto.AcsIssueResultDTO; +import cn.code.nl.module.task.job.dto.AcsTaskDTO; +import cn.code.nl.module.task.utils.AcsTaskUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 搬运任务下发管理器 + */ +@Slf4j +@Component +public class TransportTaskIssueManager { + + private static final String ACS_TASK_API = "/acs-api/wms/task"; + private static final String ACS_SERVER_ADDRESS_CONFIG_SUFFIX = "-acs-server-address"; + + @Resource + private TransportTaskMapper transportTaskMapper; + + @Resource + private ConfigApi configApi; + + /** + * 按生产区域分组下发任务 + * + * @param tasks 待下发任务 + */ + public void issueTasks(List tasks) { + tasks.stream() + .filter(task -> StrUtil.isBlank(task.getProductArea())) + .forEach(task -> + updateIssueFailed(task.getTaskId(), "生产区域为空,无法获取 ACS 服务地址", null)); + Map> taskMap = tasks.stream() + .filter(task -> StrUtil.isNotBlank(task.getProductArea())) + .collect(Collectors.groupingBy(TransportTaskDO::getProductArea)); + taskMap.forEach(this::issueProductAreaTasks); + } + + /** + * 下发单个生产区域的任务 + * + * @param productArea 生产区域 + * @param tasks 待下发任务 + */ + private void issueProductAreaTasks(String productArea, List tasks) { + List acsTasks = tasks.stream().map(AcsTaskUtil::buildAcsTaskDTO).toList(); + String requestJson = JsonUtils.toJsonString(acsTasks); + try { + String serverAddress = getAcsServerAddress(productArea); + AcsIssueResultDTO result = AcsUtil.post(serverAddress, ACS_TASK_API, acsTasks, AcsIssueResultDTO.class); + handleIssueResult(tasks, result); + } catch (Exception ex) { + log.error("自动下发任务失败,productArea={},tasks={}", productArea, requestJson, ex); + tasks.forEach(task -> updateIssueFailed(task.getTaskId(), ex.getMessage(), null)); + } + } + + /** + * 获取 ACS 服务地址 + * + * @param productArea 生产区域 + * @return ACS 服务地址 + */ + private String getAcsServerAddress(String productArea) { + String configKey = productArea + ACS_SERVER_ADDRESS_CONFIG_SUFFIX; + CommonResult result = configApi.getConfigValueByKey(configKey); + String serverAddress = result.getCheckedData(); + if (StrUtil.isBlank(serverAddress)) { + throw new ServiceException(500, "未配置 ACS 服务地址:" + configKey); + } + return serverAddress; + } + + /** + * 处理 ACS 下发响应 + * + * @param tasks 本次下发任务 + * @param result ACS 响应 + */ + private void handleIssueResult(List tasks, AcsIssueResultDTO result) { + if (result == null) { + tasks.forEach(task -> updateIssueFailed(task.getTaskId(), "ACS 返回为空", null)); + return; + } + String resultJson = JsonUtils.toJsonString(result); + List failedTasks = result.getFailedTasks() == null + ? Collections.emptyList() + : result.getFailedTasks(); + if (Boolean.FALSE.equals(result.getSuccess()) && CollUtil.isEmpty(failedTasks)) { + String errorMessage = StrUtil.blankToDefault(result.getMsg(), "ACS 下发失败"); + tasks.forEach(task -> updateIssueFailed(task.getTaskId(), errorMessage, resultJson)); + return; + } + Map failedTaskMap = failedTasks.stream() + .filter(failedTask -> failedTask.getTaskId() != null) + .collect(Collectors.toMap(AcsIssueResultDTO.FailedTask::getTaskId, Function.identity(), (first, second) -> first)); + Set failedTaskIds = failedTaskMap.keySet(); + for (TransportTaskDO task : tasks) { + if (failedTaskIds.contains(task.getTaskId())) { + updateIssueFailed(task.getTaskId(), failedTaskMap.get(task.getTaskId()).getErrorMessage(), resultJson); + } else { + transportTaskMapper.updateIssueResult(task.getTaskId(), TransportTaskStatusEnum.ISSUED.getCode(), resultJson, null); + } + } + } + + /** + * 更新任务为下发失败 + * + * @param taskId 任务标识 + * @param errorMessage 错误信息 + * @param resultJson ACS 响应 JSON + */ + private void updateIssueFailed(Long taskId, String errorMessage, String resultJson) { + transportTaskMapper.updateIssueResult(taskId, TransportTaskStatusEnum.FAILED.getCode(), resultJson, errorMessage); + } + +} diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskService.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskService.java index b7fdb0ef..5e46ec7d 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskService.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskService.java @@ -92,4 +92,9 @@ public interface TransportTaskService { */ TaskInfoDTO getTaskInfoByCode(String taskCode); + /** + * 自动下发待下发任务到 ACS + */ + void autoIssueTransportTasks(); + } diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskServiceImpl.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskServiceImpl.java index f8e26b69..b923ee1a 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskServiceImpl.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskServiceImpl.java @@ -11,8 +11,13 @@ import cn.code.nl.module.task.dal.mysql.transporttask.TransportTaskMapper; import cn.code.nl.module.task.dto.AcsFeedbackReqDTO; import cn.code.nl.module.task.dto.TaskInfoDTO; import cn.code.nl.module.task.dto.TransportTaskCreateReqDTO; -import cn.code.nl.module.task.enums.*; +import cn.code.nl.module.task.enums.CallbackStatusEnum; +import cn.code.nl.module.task.enums.FinishedTypeEnum; +import cn.code.nl.module.task.enums.TaskOperationTypeEnum; +import cn.code.nl.module.task.enums.TransportTaskStatusEnum; +import cn.code.nl.module.task.manage.TransportTaskIssueManager; import cn.code.nl.module.task.manage.TransportTaskOperationManager; +import cn.hutool.core.collection.CollUtil; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -42,21 +47,19 @@ public class TransportTaskServiceImpl implements TransportTaskService { @Resource private TransportTaskOperationManager transportTaskOperationManager; + @Resource + private TransportTaskIssueManager transportTaskIssueManager; + @Override public Long createTransportTask(TransportTaskSaveReqVO createReqVO) { - // 插入 TransportTaskDO transportTask = BeanUtils.toBean(createReqVO, TransportTaskDO.class); transportTaskMapper.insert(transportTask); - - // 返回 return transportTask.getTaskId(); } @Override public Long createTransportTaskByRpc(TransportTaskCreateReqDTO reqDTO) { - // 1. 构建 DO 并保存 TransportTaskDO task = BeanUtils.toBean(reqDTO, TransportTaskDO.class); - // 参数完整 → 待下发(040),否则 → 生成(010) task.setTaskStatus(reqDTO.getIsCreateFinish() ? TransportTaskStatusEnum.READY.getCode() : TransportTaskStatusEnum.CREATED.getCode()); @@ -70,28 +73,27 @@ public class TransportTaskServiceImpl implements TransportTaskService { @Override public void updateTransportTask(TransportTaskSaveReqVO updateReqVO) { - // 校验存在 validateTransportTaskExists(updateReqVO.getTaskId()); - // 更新 TransportTaskDO updateObj = BeanUtils.toBean(updateReqVO, TransportTaskDO.class); transportTaskMapper.updateById(updateObj); } @Override public void deleteTransportTask(Long id) { - // 校验存在 validateTransportTaskExists(id); - // 删除 transportTaskMapper.deleteById(id); } @Override - public void deleteTransportTaskListByIds(List ids) { - // 删除 + public void deleteTransportTaskListByIds(List ids) { transportTaskMapper.deleteByIds(ids); - } - + } + /** + * 校验搬运任务是否存在 + * + * @param id 任务标识 + */ private void validateTransportTaskExists(Long id) { if (transportTaskMapper.selectById(id) == null) { throw exception(TRANSPORT_TASK_NOT_EXISTS); @@ -109,55 +111,59 @@ public class TransportTaskServiceImpl implements TransportTaskService { } /** - * PC 端操作搬运任务(完成/取消/强制完成):先校验再走统一路由表分发 + * PC 端操作搬运任务,统一走状态操作分发 + * + * @param reqVO 操作请求 */ @Override @Transactional(rollbackFor = Exception.class) public void operateTransportTask(TransportTaskOperateReqVO reqVO) { - // 1. 校验任务存在 TransportTaskDO task = transportTaskMapper.selectById(reqVO.getTaskId()); if (task == null) { throw exception(TRANSPORT_TASK_NOT_EXISTS); } - // 2. 校验操作类型允许 PC 端触发 TaskOperationTypeEnum type = TaskOperationTypeEnum.getByCode(reqVO.getOperationType()); if (type == null || !type.isPcAllowed()) { throw exception(TRANSPORT_TASK_OPERATION_NOT_SUPPORTED); } - // 3. 终态校验:已完成/已取消不允许再操作 if (TransportTaskStatusEnum.FINISHED.getCode().equals(task.getTaskStatus()) || TransportTaskStatusEnum.CANCELLED.getCode().equals(task.getTaskStatus())) { throw exception(TRANSPORT_TASK_ALREADY_FINAL); } - // 4. PC 端与 ACS 的差异点:记录完成类型 if (type == TaskOperationTypeEnum.FINISHED) { task.setFinishedType(FinishedTypeEnum.MANUAL.getCode()); } else if (type == TaskOperationTypeEnum.FORCE_FINISH) { task.setFinishedType(FinishedTypeEnum.MANUAL_FORCE.getCode()); } - // 5. 构造精简反馈对象,走统一路由表分发 AcsFeedbackReqDTO reqDTO = new AcsFeedbackReqDTO(); reqDTO.setTaskId(task.getTaskId()); reqDTO.setStatus(type.getCode()); transportTaskOperationManager.dispatchOperation(task, type, reqDTO); } - /** - * 根据 taskId 查询任务全量信息:查不到返回 null,由调用方判断 - */ @Override public TaskInfoDTO getTaskInfoById(Long taskId) { TransportTaskDO task = transportTaskMapper.selectById(taskId); return TransportTaskConvert.INSTANCE.convert(task); } - /** - * 根据 taskCode 查询任务全量信息:查不到返回 null,由调用方判断 - */ @Override public TaskInfoDTO getTaskInfoByCode(String taskCode) { TransportTaskDO task = transportTaskMapper.selectByTaskCode(taskCode); return TransportTaskConvert.INSTANCE.convert(task); } + /** + * 查询待下发任务,并委托下发管理器按生产区域下发到 ACS + */ + @Override + public void autoIssueTransportTasks() { + List tasks = transportTaskMapper.selectAutoIssueReadyList(); + if (CollUtil.isEmpty(tasks)) { + log.info("自动下发任务结束:没有待下发任务"); + return; + } + transportTaskIssueManager.issueTasks(tasks); + } + } diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/utils/AcsTaskUtil.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/utils/AcsTaskUtil.java new file mode 100644 index 00000000..418f7956 --- /dev/null +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/utils/AcsTaskUtil.java @@ -0,0 +1,41 @@ +package cn.code.nl.module.task.utils; + +import cn.code.nl.framework.common.util.json.JsonUtils; +import cn.code.nl.module.task.dal.dataobject.transporttask.TransportTaskDO; +import cn.code.nl.module.task.job.dto.AcsTaskDTO; + +import java.util.UUID; + +/** + * ACS 任务工具类 + */ +public class AcsTaskUtil { + + /** + * 构建 ACS 下发任务 + * + * @param task 搬运任务 + * @return ACS 下发任务 + */ + public static AcsTaskDTO buildAcsTaskDTO(TransportTaskDO task) { + AcsTaskDTO dto = new AcsTaskDTO(); + dto.setTraceId(UUID.randomUUID().toString()); + dto.setTimestamp(System.currentTimeMillis()); + dto.setTaskId(task.getTaskId()); + dto.setTaskCode(task.getTaskCode()); + dto.setStartDeviceCode(task.getPointCode1()); + dto.setNextDeviceCode(task.getPointCode2()); + dto.setStartDeviceCode2(task.getPointCode3()); + dto.setNextDeviceCode2(task.getPointCode4()); + dto.setPriority(task.getPriority()); + dto.setVehicleCode(task.getVehicleCode()); + dto.setVehicleCode2(task.getVehicleCode2()); + dto.setTaskType(task.getAcsTaskType()); + dto.setAgvSystemType(task.getAgvSystemType()); + dto.setRemark(task.getRemark()); + dto.setPayload(JsonUtils.parseMap(task.getDispatchParam())); + dto.setProductArea(task.getProductArea()); + return dto; + } + +} diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/utils/package-info.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/utils/package-info.java new file mode 100644 index 00000000..136b5a0c --- /dev/null +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/utils/package-info.java @@ -0,0 +1,6 @@ +/** + * 本模块业务员这中使用工具类 + * @Author: liyongde + * @Date: 2026/7/23 17:02 + */ +package cn.code.nl.module.task.utils; \ No newline at end of file diff --git a/nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/api/WmsTaskExecuteApiImpl.java b/nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/api/WmsTaskExecuteApiImpl.java index 33a7fc44..d1710fc2 100644 --- a/nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/api/WmsTaskExecuteApiImpl.java +++ b/nl-module-wms/nl-module-wms-server/src/main/java/cn/code/nl/module/wms/api/WmsTaskExecuteApiImpl.java @@ -1,9 +1,11 @@ package cn.code.nl.module.wms.api; +import cn.code.nl.framework.common.enums.RpcConstants; import cn.code.nl.framework.execute.biz.api.AbstractTaskCommonApiImpl; import cn.code.nl.framework.execute.biz.api.wms.WmsTaskCommonApi; import org.springframework.context.annotation.Primary; import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** @@ -14,5 +16,6 @@ import org.springframework.web.bind.annotation.RestController; @RestController @Validated @Primary +@RequestMapping(RpcConstants.WMS_PREFIX) public class WmsTaskExecuteApiImpl extends AbstractTaskCommonApiImpl implements WmsTaskCommonApi { } From 4805e6482fb2876c35547a18999ebe75d555f6f1 Mon Sep 17 00:00:00 2001 From: liyongde <1419499670@qq.com> Date: Fri, 24 Jul 2026 13:14:43 +0800 Subject: [PATCH 5/8] =?UTF-8?q?opt=EF=BC=9A=E4=BB=BB=E5=8A=A1=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E5=8F=96=E6=B6=88=E4=B8=8EACS=E7=A1=AE=E8=AE=A4?= =?UTF-8?q?=E6=98=AF=E5=90=A6=E5=8F=AF=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/common/pojo}/AcsBaseReqDTO.java | 2 +- .../framework/common/pojo/AcsBaseRespDTO.java | 26 ++++ .../framework/common/util/http/AcsUtil.java | 35 ++++- ...ultDTO.java => AcsIssueResultRespDTO.java} | 18 +-- .../task/job/dto/AcsOperateCheckReqDTO.java | 31 ++++ .../task/job/dto/AcsOperateCheckRespDTO.java | 32 ++++ .../nl/module/task/job/dto/AcsTaskDTO.java | 5 +- .../manage/TransportTaskIssueManager.java | 12 +- .../TransportTaskOperateCheckManager.java | 139 ++++++++++++++++++ .../manage/TransportTaskOperationManager.java | 1 + .../TransportTaskServiceImpl.java | 7 + 11 files changed, 283 insertions(+), 25 deletions(-) rename {nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto => nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/pojo}/AcsBaseReqDTO.java (86%) create mode 100644 nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/pojo/AcsBaseRespDTO.java rename nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/{AcsIssueResultDTO.java => AcsIssueResultRespDTO.java} (67%) create mode 100644 nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsOperateCheckReqDTO.java create mode 100644 nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsOperateCheckRespDTO.java create mode 100644 nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskOperateCheckManager.java diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsBaseReqDTO.java b/nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/pojo/AcsBaseReqDTO.java similarity index 86% rename from nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsBaseReqDTO.java rename to nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/pojo/AcsBaseReqDTO.java index a920d0c8..23fff4ab 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsBaseReqDTO.java +++ b/nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/pojo/AcsBaseReqDTO.java @@ -1,4 +1,4 @@ -package cn.code.nl.module.task.job.dto; +package cn.code.nl.framework.common.pojo; import lombok.Data; diff --git a/nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/pojo/AcsBaseRespDTO.java b/nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/pojo/AcsBaseRespDTO.java new file mode 100644 index 00000000..91c763ea --- /dev/null +++ b/nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/pojo/AcsBaseRespDTO.java @@ -0,0 +1,26 @@ +package cn.code.nl.framework.common.pojo; + +import lombok.Data; + +/** + * acs返回基础对象 + * @Author: liyongde + * @Date: 2026/7/24 10:27 + */ +@Data +public class AcsBaseRespDTO { + /** + * 是否整体成功 + */ + private Boolean success; + + /** + * 响应编码 + */ + private String code; + + /** + * 响应消息 + */ + private String msg; +} diff --git a/nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/util/http/AcsUtil.java b/nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/util/http/AcsUtil.java index 9bf9806c..2125eba0 100644 --- a/nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/util/http/AcsUtil.java +++ b/nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/util/http/AcsUtil.java @@ -1,8 +1,15 @@ package cn.code.nl.framework.common.util.http; +import cn.code.nl.framework.common.exception.ServerException; +import cn.code.nl.framework.common.exception.ServiceException; import cn.code.nl.framework.common.util.json.JsonUtils; import cn.hutool.core.util.StrUtil; +import java.net.ConnectException; +import java.net.NoRouteToHostException; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.net.UnknownHostException; import java.util.Collections; import java.util.Map; @@ -22,7 +29,15 @@ public class AcsUtil { */ public static T post(String serverAddress, String api, Object request, Class responseType) { String url = buildUrl(serverAddress, api); - String response = HttpUtils.post(url, headers(), JsonUtils.toJsonString(request)); + String response; + try { + response = HttpUtils.post(url, headers(), JsonUtils.toJsonString(request)); + } catch (RuntimeException ex) { + if (isNetworkException(ex)) { + throw new ServerException(500, "ACS服务网络不通"); + } + throw ex; + } return JsonUtils.parseObject(response, responseType); } @@ -42,4 +57,22 @@ public class AcsUtil { return Collections.singletonMap("Content-Type", "application/json;charset=UTF-8"); } + /** + * 判断是否为 ACS 网络连接异常 + */ + private static boolean isNetworkException(Throwable ex) { + Throwable cause = ex; + while (cause != null) { + if (cause instanceof ConnectException + || cause instanceof SocketTimeoutException + || cause instanceof UnknownHostException + || cause instanceof NoRouteToHostException + || cause instanceof SocketException) { + return true; + } + cause = cause.getCause(); + } + return false; + } + } diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsIssueResultDTO.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsIssueResultRespDTO.java similarity index 67% rename from nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsIssueResultDTO.java rename to nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsIssueResultRespDTO.java index b8bd4422..388bce41 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsIssueResultDTO.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsIssueResultRespDTO.java @@ -1,5 +1,6 @@ package cn.code.nl.module.task.job.dto; +import cn.code.nl.framework.common.pojo.AcsBaseRespDTO; import lombok.Data; import java.util.List; @@ -8,22 +9,7 @@ import java.util.List; * ACS 任务下发响应 */ @Data -public class AcsIssueResultDTO { - - /** - * 是否整体成功 - */ - private Boolean success; - - /** - * 响应编码 - */ - private String code; - - /** - * 响应消息 - */ - private String msg; +public class AcsIssueResultRespDTO extends AcsBaseRespDTO { /** * 下发失败的任务 diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsOperateCheckReqDTO.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsOperateCheckReqDTO.java new file mode 100644 index 00000000..876c5865 --- /dev/null +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsOperateCheckReqDTO.java @@ -0,0 +1,31 @@ +package cn.code.nl.module.task.job.dto; + +import lombok.Data; + +/** + * ACS 任务操作校验请求 + */ +@Data +public class AcsOperateCheckReqDTO { + + /** + * 任务标识 + */ + private Long taskId; + + /** + * 任务编码 + */ + private String taskCode; + + /** + * 操作类型 + */ + private String operationType; + + /** + * 生产区域 + */ + private String productArea; + +} diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsOperateCheckRespDTO.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsOperateCheckRespDTO.java new file mode 100644 index 00000000..ab4278bb --- /dev/null +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsOperateCheckRespDTO.java @@ -0,0 +1,32 @@ +package cn.code.nl.module.task.job.dto; + +import cn.code.nl.framework.common.pojo.AcsBaseRespDTO; +import lombok.Data; + +/** + * ACS 任务操作校验响应 + */ +@Data +public class AcsOperateCheckRespDTO extends AcsBaseRespDTO { + + /** + * 是否允许操作 + */ + private Boolean enableOperate; + + /** + * 是否允许操作,兼容 ACS 字段 + */ + private Boolean canOperate; + + /** + * 是否允许操作,兼容通用 data 字段 + */ + private Boolean data; + + /** + * 不允许操作的原因 + */ + private String message; + +} diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsTaskDTO.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsTaskDTO.java index 0c3a2153..7aa6bf79 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsTaskDTO.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/job/dto/AcsTaskDTO.java @@ -2,15 +2,18 @@ package cn.code.nl.module.task.job.dto; import lombok.Data; +import cn.code.nl.framework.common.pojo.AcsBaseReqDTO; + import java.util.Map; /** * 下发给ACS的实体 + * * @Author: liyongde * @Date: 2026/7/23 17:10 */ @Data -public class AcsTaskDTO extends AcsBaseReqDTO{ +public class AcsTaskDTO extends AcsBaseReqDTO { /** * 任务标识 */ diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskIssueManager.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskIssueManager.java index 4224dd45..e26ece3c 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskIssueManager.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskIssueManager.java @@ -8,7 +8,7 @@ import cn.code.nl.module.infra.api.config.ConfigApi; import cn.code.nl.module.task.dal.dataobject.transporttask.TransportTaskDO; import cn.code.nl.module.task.dal.mysql.transporttask.TransportTaskMapper; import cn.code.nl.module.task.enums.TransportTaskStatusEnum; -import cn.code.nl.module.task.job.dto.AcsIssueResultDTO; +import cn.code.nl.module.task.job.dto.AcsIssueResultRespDTO; import cn.code.nl.module.task.job.dto.AcsTaskDTO; import cn.code.nl.module.task.utils.AcsTaskUtil; import cn.hutool.core.collection.CollUtil; @@ -67,7 +67,7 @@ public class TransportTaskIssueManager { String requestJson = JsonUtils.toJsonString(acsTasks); try { String serverAddress = getAcsServerAddress(productArea); - AcsIssueResultDTO result = AcsUtil.post(serverAddress, ACS_TASK_API, acsTasks, AcsIssueResultDTO.class); + AcsIssueResultRespDTO result = AcsUtil.post(serverAddress, ACS_TASK_API, acsTasks, AcsIssueResultRespDTO.class); handleIssueResult(tasks, result); } catch (Exception ex) { log.error("自动下发任务失败,productArea={},tasks={}", productArea, requestJson, ex); @@ -97,13 +97,13 @@ public class TransportTaskIssueManager { * @param tasks 本次下发任务 * @param result ACS 响应 */ - private void handleIssueResult(List tasks, AcsIssueResultDTO result) { + private void handleIssueResult(List tasks, AcsIssueResultRespDTO result) { if (result == null) { tasks.forEach(task -> updateIssueFailed(task.getTaskId(), "ACS 返回为空", null)); return; } String resultJson = JsonUtils.toJsonString(result); - List failedTasks = result.getFailedTasks() == null + List failedTasks = result.getFailedTasks() == null ? Collections.emptyList() : result.getFailedTasks(); if (Boolean.FALSE.equals(result.getSuccess()) && CollUtil.isEmpty(failedTasks)) { @@ -111,9 +111,9 @@ public class TransportTaskIssueManager { tasks.forEach(task -> updateIssueFailed(task.getTaskId(), errorMessage, resultJson)); return; } - Map failedTaskMap = failedTasks.stream() + Map failedTaskMap = failedTasks.stream() .filter(failedTask -> failedTask.getTaskId() != null) - .collect(Collectors.toMap(AcsIssueResultDTO.FailedTask::getTaskId, Function.identity(), (first, second) -> first)); + .collect(Collectors.toMap(AcsIssueResultRespDTO.FailedTask::getTaskId, Function.identity(), (first, second) -> first)); Set failedTaskIds = failedTaskMap.keySet(); for (TransportTaskDO task : tasks) { if (failedTaskIds.contains(task.getTaskId())) { diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskOperateCheckManager.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskOperateCheckManager.java new file mode 100644 index 00000000..2acafce2 --- /dev/null +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskOperateCheckManager.java @@ -0,0 +1,139 @@ +package cn.code.nl.module.task.manage; + +import cn.code.nl.framework.common.exception.ServiceException; +import cn.code.nl.framework.common.pojo.CommonResult; +import cn.code.nl.framework.common.util.http.AcsUtil; +import cn.code.nl.framework.common.util.json.JsonUtils; +import cn.code.nl.module.infra.api.config.ConfigApi; +import cn.code.nl.module.task.dal.dataobject.transporttask.TransportTaskDO; +import cn.code.nl.module.task.enums.TaskOperationTypeEnum; +import cn.code.nl.module.task.job.dto.AcsOperateCheckRespDTO; +import cn.code.nl.module.task.job.dto.AcsOperateCheckReqDTO; +import cn.hutool.core.util.StrUtil; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * PC 端任务操作 ACS 校验管理器 + */ +@Slf4j +@Component +public class TransportTaskOperateCheckManager { + + private static final String TASK_OPERATE_ENABLE_CONFIG_KEY = "task-operate-enable"; + private static final String TASK_OPERATE_ENABLE_VALUE = "1"; + private static final String ACS_OPERATE_CHECK_API = "/acs-api/wms/check-enable-operate"; + private static final String ACS_SERVER_ADDRESS_CONFIG_SUFFIX = "-acs-server-address"; + + @Resource + private ConfigApi configApi; + + /** + * 按配置校验 PC 端是否允许完成或取消任务 + * + * @param task 任务信息 + * @param type 操作类型 + */ + public void checkEnableOperate(TransportTaskDO task, TaskOperationTypeEnum type) { + if (!needCheckAcs()) { + return; + } + String serverAddress = getAcsServerAddress(task.getProductArea()); + AcsOperateCheckReqDTO reqDTO = buildReqDTO(task, type); + AcsOperateCheckRespDTO result; + try { + result = AcsUtil.post(serverAddress, ACS_OPERATE_CHECK_API, reqDTO, AcsOperateCheckRespDTO.class); + } catch (ServiceException ex) { + log.error("ACS 操作校验请求失败,reqDTO={}", JsonUtils.toJsonString(reqDTO), ex); + throw ex; + } catch (Exception ex) { + log.error("ACS 操作校验请求失败,reqDTO={}", JsonUtils.toJsonString(reqDTO), ex); + throw new ServiceException(500, "ACS操作校验失败"); + } + handleCheckResult(reqDTO, result); + } + + /** + * 判断是否需要请求 ACS 校验 + */ + private boolean needCheckAcs() { + CommonResult result = configApi.getConfigValueByKey(TASK_OPERATE_ENABLE_CONFIG_KEY); + return TASK_OPERATE_ENABLE_VALUE.equals(result.getCheckedData()); + } + + /** + * 获取 ACS 服务地址 + * + * @param productArea 生产区域 + * @return ACS 服务地址 + */ + private String getAcsServerAddress(String productArea) { + if (StrUtil.isBlank(productArea)) { + throw new ServiceException(500, "生产区域为空,无法获取 ACS 服务地址"); + } + String configKey = productArea + ACS_SERVER_ADDRESS_CONFIG_SUFFIX; + CommonResult result = configApi.getConfigValueByKey(configKey); + String serverAddress = result.getCheckedData(); + if (StrUtil.isBlank(serverAddress)) { + throw new ServiceException(500, "未配置 ACS 服务地址:" + configKey); + } + return serverAddress; + } + + /** + * 构建 ACS 操作校验请求 + */ + private AcsOperateCheckReqDTO buildReqDTO(TransportTaskDO task, TaskOperationTypeEnum type) { + AcsOperateCheckReqDTO reqDTO = new AcsOperateCheckReqDTO(); + reqDTO.setTaskId(task.getTaskId()); + reqDTO.setTaskCode(task.getTaskCode()); + reqDTO.setOperationType(type.getCode()); + reqDTO.setProductArea(task.getProductArea()); + return reqDTO; + } + + /** + * 处理 ACS 操作校验结果 + */ + private void handleCheckResult(AcsOperateCheckReqDTO reqDTO, AcsOperateCheckRespDTO result) { + if (result == null) { + throw new ServiceException(500, "ACS 操作校验返回为空"); + } + Boolean enableOperate = getEnableOperate(result); + if (Boolean.TRUE.equals(enableOperate)) { + return; + } + String message = getMessage(result); + log.warn("ACS 拒绝 PC 端任务操作,reqDTO={},result={}", + JsonUtils.toJsonString(reqDTO), JsonUtils.toJsonString(result)); + throw new ServiceException(500, message); + } + + /** + * 获取 ACS 是否允许操作 + */ + private Boolean getEnableOperate(AcsOperateCheckRespDTO result) { + if (result.getEnableOperate() != null) { + return result.getEnableOperate(); + } + if (result.getCanOperate() != null) { + return result.getCanOperate(); + } + if (result.getData() != null) { + return result.getData(); + } + return result.getSuccess(); + } + + /** + * 获取 ACS 拒绝原因 + */ + private String getMessage(AcsOperateCheckRespDTO result) { + if (StrUtil.isNotBlank(result.getMessage())) { + return result.getMessage(); + } + return StrUtil.blankToDefault(result.getMsg(), "ACS 不允许执行该操作"); + } + +} diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskOperationManager.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskOperationManager.java index 9e9ee168..0a09e89b 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskOperationManager.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/manage/TransportTaskOperationManager.java @@ -73,6 +73,7 @@ public class TransportTaskOperationManager { handler.accept(task, reqDTO); } catch (Exception ex) { log.error("[messageResend][执行异常][lockKey={}]", task.getTaskId(), ex); + throw new ServiceException(500, ex.getMessage()); } finally { if (lock.isHeldByCurrentThread()) { lock.unlock(); diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskServiceImpl.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskServiceImpl.java index b923ee1a..3b687f7d 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskServiceImpl.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskServiceImpl.java @@ -16,6 +16,7 @@ import cn.code.nl.module.task.enums.FinishedTypeEnum; import cn.code.nl.module.task.enums.TaskOperationTypeEnum; import cn.code.nl.module.task.enums.TransportTaskStatusEnum; import cn.code.nl.module.task.manage.TransportTaskIssueManager; +import cn.code.nl.module.task.manage.TransportTaskOperateCheckManager; import cn.code.nl.module.task.manage.TransportTaskOperationManager; import cn.hutool.core.collection.CollUtil; import jakarta.annotation.Resource; @@ -50,6 +51,9 @@ public class TransportTaskServiceImpl implements TransportTaskService { @Resource private TransportTaskIssueManager transportTaskIssueManager; + @Resource + private TransportTaskOperateCheckManager transportTaskOperateCheckManager; + @Override public Long createTransportTask(TransportTaskSaveReqVO createReqVO) { TransportTaskDO transportTask = BeanUtils.toBean(createReqVO, TransportTaskDO.class); @@ -130,6 +134,9 @@ public class TransportTaskServiceImpl implements TransportTaskService { || TransportTaskStatusEnum.CANCELLED.getCode().equals(task.getTaskStatus())) { throw exception(TRANSPORT_TASK_ALREADY_FINAL); } + if (type == TaskOperationTypeEnum.FINISHED || type == TaskOperationTypeEnum.CANCELLED) { + transportTaskOperateCheckManager.checkEnableOperate(task, type); + } if (type == TaskOperationTypeEnum.FINISHED) { task.setFinishedType(FinishedTypeEnum.MANUAL.getCode()); } else if (type == TaskOperationTypeEnum.FORCE_FINISH) { From 62454c77c16509c135290c234e22bb9215719ad2 Mon Sep 17 00:00:00 2001 From: liyongde <1419499670@qq.com> Date: Fri, 24 Jul 2026 16:23:19 +0800 Subject: [PATCH 6/8] =?UTF-8?q?feat=EF=BC=9APC=20=E4=B8=8B=E5=8F=91?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/common/util/http/AcsUtil.java | 2 +- .../api/classstandard/ClassStandardApi.java | 34 ++ .../base/api/ClassStandardApiController.java | 46 +++ .../vo/ClassStandardSimpleRespVO.java | 3 + .../nl/module/task/api/TransportTaskApi.java | 4 + .../module/task/enums/ErrorCodeConstants.java | 1 + .../task/enums/TaskCreateModelEnum.java | 22 ++ nl-module-task/nl-module-task-server/pom.xml | 7 +- .../module/task/api/TransportTaskApiImpl.java | 6 + .../TransportTaskController.java | 233 +++++++------ .../vo/TransportTaskPageReqVO.java | 5 +- .../transporttask/vo/TransportTaskRespVO.java | 324 +++++++++--------- .../transporttask/TransportTaskMapper.java | 2 +- .../transporttask/TransportTaskService.java | 7 + .../TransportTaskServiceImpl.java | 28 ++ .../src/api/task/transporttask/index.ts | 4 + .../src/views/base/materialbase/data.ts | 200 ++++++++--- .../src/views/task/transporttask/data.ts | 44 ++- .../src/views/task/transporttask/index.vue | 43 ++- .../packages/constants/src/dict-enum.ts | 2 + 20 files changed, 687 insertions(+), 330 deletions(-) create mode 100644 nl-module-base/nl-module-base-api/src/main/java/cn/code/nl/module/base/api/classstandard/ClassStandardApi.java create mode 100644 nl-module-base/nl-module-base-server/src/main/java/cn/code/nl/module/base/api/ClassStandardApiController.java create mode 100644 nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/enums/TaskCreateModelEnum.java diff --git a/nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/util/http/AcsUtil.java b/nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/util/http/AcsUtil.java index 2125eba0..0ada5947 100644 --- a/nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/util/http/AcsUtil.java +++ b/nl-framework/nl-common/src/main/java/cn/code/nl/framework/common/util/http/AcsUtil.java @@ -34,7 +34,7 @@ public class AcsUtil { response = HttpUtils.post(url, headers(), JsonUtils.toJsonString(request)); } catch (RuntimeException ex) { if (isNetworkException(ex)) { - throw new ServerException(500, "ACS服务网络不通"); + throw new ServiceException(500, "ACS服务网络不通"); } throw ex; } diff --git a/nl-module-base/nl-module-base-api/src/main/java/cn/code/nl/module/base/api/classstandard/ClassStandardApi.java b/nl-module-base/nl-module-base-api/src/main/java/cn/code/nl/module/base/api/classstandard/ClassStandardApi.java new file mode 100644 index 00000000..503e325a --- /dev/null +++ b/nl-module-base/nl-module-base-api/src/main/java/cn/code/nl/module/base/api/classstandard/ClassStandardApi.java @@ -0,0 +1,34 @@ +package cn.code.nl.module.base.api.classstandard; + +import cn.code.nl.framework.common.pojo.CommonResult; +import cn.code.nl.module.base.enums.ApiConstants; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; + +/** + * RPC 服务 - 基础数据分类标准 + * + * @author zhouz + */ +@FeignClient(name = ApiConstants.NAME) +@Tag(name = "RPC 服务 - 基础数据分类标准") +public interface ClassStandardApi { + + String PREFIX = ApiConstants.PREFIX + "/class-standard"; + + /** + * 根据分类编码获取该分类及所有子分类编码 + * + * @param classCode 分类编码 + * @return 分类编码列表 + */ + @GetMapping(PREFIX + "/code-list-by-code") + @Operation(summary = "根据分类编码获取该分类及所有子分类编码") + CommonResult> getClassStandardCodeListByCode(@RequestParam("classCode") String classCode); + +} diff --git a/nl-module-base/nl-module-base-server/src/main/java/cn/code/nl/module/base/api/ClassStandardApiController.java b/nl-module-base/nl-module-base-server/src/main/java/cn/code/nl/module/base/api/ClassStandardApiController.java new file mode 100644 index 00000000..78f90bbe --- /dev/null +++ b/nl-module-base/nl-module-base-server/src/main/java/cn/code/nl/module/base/api/ClassStandardApiController.java @@ -0,0 +1,46 @@ +package cn.code.nl.module.base.api; + +import cn.code.nl.framework.common.pojo.CommonResult; +import cn.code.nl.module.base.api.classstandard.ClassStandardApi; +import cn.code.nl.module.base.dal.dataobject.classstandard.ClassStandardDO; +import cn.code.nl.module.base.service.classstandard.ClassStandardService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import static cn.code.nl.framework.common.pojo.CommonResult.success; +import static cn.code.nl.framework.common.util.collection.CollectionUtils.convertList; + +/** + * RPC API - 基础数据分类标准(供其它模块 Feign 调用) + * + * @author zhouz + */ +@Tag(name = "RPC API - 基础数据分类标准") +@RestController +@RequestMapping("/rpc-api/base/class-standard") +@Validated +public class ClassStandardApiController implements ClassStandardApi { + + @Resource + private ClassStandardService classStandardService; + + /** + * 根据分类编码获取该分类及所有子分类编码 + */ + @GetMapping("/code-list-by-code") + @Operation(summary = "根据分类编码获取该分类及所有子分类编码") + @Override + public CommonResult> getClassStandardCodeListByCode(@RequestParam("classCode") String classCode) { + List list = classStandardService.getClassStandardListByCode(classCode); + return success(convertList(list, ClassStandardDO::getClassCode)); + } + +} diff --git a/nl-module-base/nl-module-base-server/src/main/java/cn/code/nl/module/base/controller/admin/classstandard/vo/ClassStandardSimpleRespVO.java b/nl-module-base/nl-module-base-server/src/main/java/cn/code/nl/module/base/controller/admin/classstandard/vo/ClassStandardSimpleRespVO.java index a4de7532..12ba7fe9 100644 --- a/nl-module-base/nl-module-base-server/src/main/java/cn/code/nl/module/base/controller/admin/classstandard/vo/ClassStandardSimpleRespVO.java +++ b/nl-module-base/nl-module-base-server/src/main/java/cn/code/nl/module/base/controller/admin/classstandard/vo/ClassStandardSimpleRespVO.java @@ -15,6 +15,9 @@ public class ClassStandardSimpleRespVO { @Schema(description = "分类标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long classId; + @Schema(description = "分类编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "原材料") + private String classCode; + @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原材料") private String className; diff --git a/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/api/TransportTaskApi.java b/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/api/TransportTaskApi.java index 05928de0..bae20f63 100644 --- a/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/api/TransportTaskApi.java +++ b/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/api/TransportTaskApi.java @@ -34,6 +34,10 @@ public interface TransportTaskApi { @Operation(summary = "接收 LMS/WMS 业务处理结果") CommonResult receiveCallbackResult(@Valid @RequestBody TaskCallbackResultReqDTO reqDTO); + @PostMapping(PREFIX + "/issue") + @Operation(summary = "根据 taskId 下发搬运任务") + CommonResult issueTransportTask(@RequestParam("taskId") Long taskId); + @GetMapping(PREFIX + "/getTaskById") @Operation(summary = "根据 taskId 查询任务") CommonResult getTaskById(@RequestParam("taskId") Long taskId); diff --git a/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/enums/ErrorCodeConstants.java b/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/enums/ErrorCodeConstants.java index 41e2a96a..6d7f5290 100644 --- a/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/enums/ErrorCodeConstants.java +++ b/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/enums/ErrorCodeConstants.java @@ -16,5 +16,6 @@ public interface ErrorCodeConstants { ErrorCode TRANSPORT_TASK_RUNNING_ALREADY_EXIST = new ErrorCode(5005, "已存在运行中的任务"); ErrorCode TRANSPORT_TASK_OPERATION_NOT_SUPPORTED = new ErrorCode(5006, "不支持的任务操作类型"); ErrorCode TRANSPORT_TASK_ALREADY_FINAL = new ErrorCode(5007, "任务已处于终态,不允许操作"); + ErrorCode TRANSPORT_TASK_AUTO_ISSUE_NOT_ALLOW_MANUAL = new ErrorCode(5008, "自动任务不允许手动下发"); } diff --git a/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/enums/TaskCreateModelEnum.java b/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/enums/TaskCreateModelEnum.java new file mode 100644 index 00000000..6c919a64 --- /dev/null +++ b/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/enums/TaskCreateModelEnum.java @@ -0,0 +1,22 @@ +package cn.code.nl.module.task.enums; + +import lombok.Getter; + +/** + * + * @Author: liyongde + * @Date: 2026/7/24 16:13 + */ +@Getter +public enum TaskCreateModelEnum { + AUTO("1", "自动创建"), + MANUAL("0", "创建人工"); + + private final String code; + private final String name; + + TaskCreateModelEnum(String code, String name) { + this.code = code; + this.name = name; + } +} diff --git a/nl-module-task/nl-module-task-server/pom.xml b/nl-module-task/nl-module-task-server/pom.xml index 31c04b18..0941178c 100644 --- a/nl-module-task/nl-module-task-server/pom.xml +++ b/nl-module-task/nl-module-task-server/pom.xml @@ -42,6 +42,11 @@ nl-module-task-api ${revision} + + cn.nl.cloud + nl-module-base-api + ${revision} + @@ -164,4 +169,4 @@ - \ No newline at end of file + diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/api/TransportTaskApiImpl.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/api/TransportTaskApiImpl.java index c397dcac..e84a7c0a 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/api/TransportTaskApiImpl.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/api/TransportTaskApiImpl.java @@ -36,6 +36,12 @@ public class TransportTaskApiImpl implements TransportTaskApi { return success(true); } + @Override + public CommonResult issueTransportTask(Long taskId) { + transportTaskService.issueTransportTask(taskId); + return success(true); + } + @Override public CommonResult getTaskById(Long taskId) { return success(transportTaskService.getTaskInfoById(taskId)); diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/controller/admin/transporttask/TransportTaskController.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/controller/admin/transporttask/TransportTaskController.java index dc056006..3bc88d3a 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/controller/admin/transporttask/TransportTaskController.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/controller/admin/transporttask/TransportTaskController.java @@ -1,112 +1,121 @@ -package cn.code.nl.module.task.controller.admin.transporttask; - -import org.springframework.web.bind.annotation.*; -import jakarta.annotation.Resource; -import org.springframework.validation.annotation.Validated; -import org.springframework.security.access.prepost.PreAuthorize; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.Operation; - -import jakarta.validation.constraints.*; -import jakarta.validation.*; -import jakarta.servlet.http.*; -import java.util.*; -import java.io.IOException; - -import cn.code.nl.framework.common.pojo.PageParam; -import cn.code.nl.framework.common.pojo.PageResult; -import cn.code.nl.framework.common.pojo.CommonResult; -import cn.code.nl.framework.common.util.object.BeanUtils; -import static cn.code.nl.framework.common.pojo.CommonResult.success; - -import cn.code.nl.framework.excel.core.util.ExcelUtils; - -import cn.code.nl.framework.apilog.core.annotation.ApiAccessLog; -import static cn.code.nl.framework.apilog.core.enums.OperateTypeEnum.*; - -import cn.code.nl.module.task.controller.admin.transporttask.vo.*; -import cn.code.nl.module.task.dal.dataobject.transporttask.TransportTaskDO; -import cn.code.nl.module.task.service.transporttask.TransportTaskService; - -@Tag(name = "管理后台 - 搬运任务") -@RestController -@RequestMapping("/task/transport-task") -@Validated -public class TransportTaskController { - - @Resource - private TransportTaskService transportTaskService; - - @PostMapping("/create") - @Operation(summary = "创建搬运任务") - @PreAuthorize("@ss.hasPermission('task:transport-task:create')") - public CommonResult createTransportTask(@Valid @RequestBody TransportTaskSaveReqVO createReqVO) { - return success(transportTaskService.createTransportTask(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新搬运任务") - @PreAuthorize("@ss.hasPermission('task:transport-task:update')") - public CommonResult updateTransportTask(@Valid @RequestBody TransportTaskSaveReqVO updateReqVO) { - transportTaskService.updateTransportTask(updateReqVO); - return success(true); - } - - @PostMapping("/operate") - @Operation(summary = "PC 端操作搬运任务(完成/取消/强制完成)") - @PreAuthorize("@ss.hasPermission('task:transport-task:operate')") - public CommonResult operateTransportTask(@Valid @RequestBody TransportTaskOperateReqVO reqVO) { - transportTaskService.operateTransportTask(reqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除搬运任务") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('task:transport-task:delete')") - public CommonResult deleteTransportTask(@RequestParam("id") Long id) { - transportTaskService.deleteTransportTask(id); - return success(true); - } - - @DeleteMapping("/delete-list") - @Parameter(name = "ids", description = "编号", required = true) - @Operation(summary = "批量删除搬运任务") - @PreAuthorize("@ss.hasPermission('task:transport-task:delete')") - public CommonResult deleteTransportTaskList(@RequestParam("ids") List ids) { - transportTaskService.deleteTransportTaskListByIds(ids); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得搬运任务") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('task:transport-task:query')") - public CommonResult getTransportTask(@RequestParam("id") Long id) { - TransportTaskDO transportTask = transportTaskService.getTransportTask(id); - return success(BeanUtils.toBean(transportTask, TransportTaskRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获得搬运任务分页") - @PreAuthorize("@ss.hasPermission('task:transport-task:query')") - public CommonResult> getTransportTaskPage(@Valid TransportTaskPageReqVO pageReqVO) { - PageResult pageResult = transportTaskService.getTransportTaskPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, TransportTaskRespVO.class)); - } - - @GetMapping("/export-excel") - @Operation(summary = "导出搬运任务 Excel") - @PreAuthorize("@ss.hasPermission('task:transport-task:export')") - @ApiAccessLog(operateType = EXPORT) - public void exportTransportTaskExcel(@Valid TransportTaskPageReqVO pageReqVO, - HttpServletResponse response) throws IOException { - pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); - List list = transportTaskService.getTransportTaskPage(pageReqVO).getList(); - // 导出 Excel - ExcelUtils.write(response, "搬运任务.xls", "数据", TransportTaskRespVO.class, - BeanUtils.toBean(list, TransportTaskRespVO.class)); - } - -} \ No newline at end of file +package cn.code.nl.module.task.controller.admin.transporttask; + +import org.springframework.web.bind.annotation.*; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import jakarta.validation.constraints.*; +import jakarta.validation.*; +import jakarta.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.code.nl.framework.common.pojo.PageParam; +import cn.code.nl.framework.common.pojo.PageResult; +import cn.code.nl.framework.common.pojo.CommonResult; +import cn.code.nl.framework.common.util.object.BeanUtils; +import static cn.code.nl.framework.common.pojo.CommonResult.success; + +import cn.code.nl.framework.excel.core.util.ExcelUtils; + +import cn.code.nl.framework.apilog.core.annotation.ApiAccessLog; +import static cn.code.nl.framework.apilog.core.enums.OperateTypeEnum.*; + +import cn.code.nl.module.task.controller.admin.transporttask.vo.*; +import cn.code.nl.module.task.dal.dataobject.transporttask.TransportTaskDO; +import cn.code.nl.module.task.service.transporttask.TransportTaskService; + +@Tag(name = "管理后台 - 搬运任务") +@RestController +@RequestMapping("/task/transport-task") +@Validated +public class TransportTaskController { + + @Resource + private TransportTaskService transportTaskService; + + @PostMapping("/create") + @Operation(summary = "创建搬运任务") + @PreAuthorize("@ss.hasPermission('task:transport-task:create')") + public CommonResult createTransportTask(@Valid @RequestBody TransportTaskSaveReqVO createReqVO) { + return success(transportTaskService.createTransportTask(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新搬运任务") + @PreAuthorize("@ss.hasPermission('task:transport-task:update')") + public CommonResult updateTransportTask(@Valid @RequestBody TransportTaskSaveReqVO updateReqVO) { + transportTaskService.updateTransportTask(updateReqVO); + return success(true); + } + + @PostMapping("/operate") + @Operation(summary = "PC 端操作搬运任务(完成/取消/强制完成)") + @PreAuthorize("@ss.hasPermission('task:transport-task:operate')") + public CommonResult operateTransportTask(@Valid @RequestBody TransportTaskOperateReqVO reqVO) { + transportTaskService.operateTransportTask(reqVO); + return success(true); + } + + @PostMapping("/issue") + @Operation(summary = "PC 端下发搬运任务到 ACS") + @Parameter(name = "taskId", description = "任务ID", required = true) + @PreAuthorize("@ss.hasPermission('task:transport-task:issue')") + public CommonResult issueTransportTask(@RequestParam("taskId") Long taskId) { + transportTaskService.issueTransportTask(taskId); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除搬运任务") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('task:transport-task:delete')") + public CommonResult deleteTransportTask(@RequestParam("id") Long id) { + transportTaskService.deleteTransportTask(id); + return success(true); + } + + @DeleteMapping("/delete-list") + @Parameter(name = "ids", description = "编号", required = true) + @Operation(summary = "批量删除搬运任务") + @PreAuthorize("@ss.hasPermission('task:transport-task:delete')") + public CommonResult deleteTransportTaskList(@RequestParam("ids") List ids) { + transportTaskService.deleteTransportTaskListByIds(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得搬运任务") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('task:transport-task:query')") + public CommonResult getTransportTask(@RequestParam("id") Long id) { + TransportTaskDO transportTask = transportTaskService.getTransportTask(id); + return success(BeanUtils.toBean(transportTask, TransportTaskRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得搬运任务分页") + @PreAuthorize("@ss.hasPermission('task:transport-task:query')") + public CommonResult> getTransportTaskPage(@Valid TransportTaskPageReqVO pageReqVO) { + PageResult pageResult = transportTaskService.getTransportTaskPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, TransportTaskRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出搬运任务 Excel") + @PreAuthorize("@ss.hasPermission('task:transport-task:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportTransportTaskExcel(@Valid TransportTaskPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = transportTaskService.getTransportTaskPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "搬运任务.xls", "数据", TransportTaskRespVO.class, + BeanUtils.toBean(list, TransportTaskRespVO.class)); + } + +} diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/controller/admin/transporttask/vo/TransportTaskPageReqVO.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/controller/admin/transporttask/vo/TransportTaskPageReqVO.java index 1576581b..ddb17613 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/controller/admin/transporttask/vo/TransportTaskPageReqVO.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/controller/admin/transporttask/vo/TransportTaskPageReqVO.java @@ -34,6 +34,9 @@ public class TransportTaskPageReqVO extends PageParam { @Schema(description = "任务类型", example = "2") private String taskType; + @Schema(description = "任务类型及子类型编码列表", hidden = true) + private List taskTypeList; + @Schema(description = "任务状态(支持多选)", example = "[\"10\", \"50\"]") private List taskStatus; @@ -119,4 +122,4 @@ public class TransportTaskPageReqVO extends PageParam { @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime[] createTime; -} \ No newline at end of file +} diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/controller/admin/transporttask/vo/TransportTaskRespVO.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/controller/admin/transporttask/vo/TransportTaskRespVO.java index 387e8aa4..80e71307 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/controller/admin/transporttask/vo/TransportTaskRespVO.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/controller/admin/transporttask/vo/TransportTaskRespVO.java @@ -1,162 +1,162 @@ -package cn.code.nl.module.task.controller.admin.transporttask.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import java.util.*; -import org.springframework.format.annotation.DateTimeFormat; -import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; -import cn.code.nl.framework.excel.core.annotations.DictFormat; -import cn.code.nl.framework.excel.core.convert.DictConvert; - -@Schema(description = "管理后台 - 搬运任务 Response VO") -@Data -@ExcelIgnoreUnannotated -public class TransportTaskRespVO { - - @Schema(description = "任务标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "11528") - @ExcelProperty("任务标识") - private Long taskId; - - @Schema(description = "任务编码", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("任务编码") - private String taskCode; - - @Schema(description = "任务名称", example = "张三") - @ExcelProperty("任务名称") - private String taskName; - - @Schema(description = "业务归属服务:LMS/WMS,用于完成取消事件一级路由", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("业务归属服务:LMS/WMS,用于完成取消事件一级路由") - private String ownerService; - - @Schema(description = "业务类型", example = "2") - @ExcelProperty("业务类型") - private String bizType; - - @Schema(description = "业务侧标识", example = "31008") - @ExcelProperty("业务侧标识") - private String bizId; - - @Schema(description = "业务回调处理器编码") - @ExcelProperty("业务回调处理器编码") - private String handleCode; - - @Schema(description = "任务类型", example = "2") - @ExcelProperty("任务类型") - private String taskType; - - @Schema(description = "任务状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - @ExcelProperty("任务状态") - private String taskStatus; - - @Schema(description = "ACS任务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @ExcelProperty("ACS任务类型") - private String acsTaskType; - - @Schema(description = "AGV系统类型", example = "1") - @ExcelProperty("AGV系统类型") - private String agvSystemType; - - @Schema(description = "ACS外部任务号") - @ExcelProperty("ACS外部任务号") - private String externalTaskNo; - - @Schema(description = "取货点1") - @ExcelProperty("取货点1") - private String pointCode1; - - @Schema(description = "放货点1") - @ExcelProperty("放货点1") - private String pointCode2; - - @Schema(description = "取货点2") - @ExcelProperty("取货点2") - private String pointCode3; - - @Schema(description = "放货点2") - @ExcelProperty("放货点2") - private String pointCode4; - - @Schema(description = "载具类型", example = "2") - @ExcelProperty("载具类型") - private String vehicleType; - - @Schema(description = "载具数量", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("载具数量") - private Long vehicleQty; - - @Schema(description = "载具编码") - @ExcelProperty("载具编码") - private String vehicleCode; - - @Schema(description = "载具编码2") - @ExcelProperty("载具编码2") - private String vehicleCode2; - - @Schema(description = "车号") - @ExcelProperty("车号") - private String carNo; - - @Schema(description = "优先级", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("优先级") - private String priority; - - @Schema(description = "生产区域") - @ExcelProperty("生产区域") - private String productArea; - - @Schema(description = "是否自动下发", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("是否自动下发") - private String isAutoIssue; - - @Schema(description = "任务组标识", example = "21169") - @ExcelProperty("任务组标识") - private Long taskGroupId; - - @Schema(description = "任务组顺序号", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("任务组顺序号") - private Long sortSeq; - - @Schema(description = "任务完成类型", example = "1") - @ExcelProperty("任务完成类型") - private String finishedType; - - @Schema(description = "业务回调状态:PENDING/SUCCESS/FAILED", example = "2") - @ExcelProperty("业务回调状态:PENDING/SUCCESS/FAILED") - private String callbackStatus; - - @Schema(description = "业务回调重试次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "2146") - @ExcelProperty("业务回调重试次数") - private Integer callbackRetryCount; - - @Schema(description = "业务回调失败原因") - @ExcelProperty("业务回调失败原因") - private String callbackErrorMsg; - - @Schema(description = "生成方式", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty(value = "生成方式", converter = DictConvert.class) - @DictFormat("user_type") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 - private String createMode; - - @Schema(description = "创建任务请求参数") - @ExcelProperty("创建任务请求参数") - private String requestParam; - - @Schema(description = "下发ACS的AcsTaskDto扩展报文") - @ExcelProperty("下发ACS的AcsTaskDto扩展报文") - private String dispatchParam; - - @Schema(description = "ACS反馈参数") - @ExcelProperty("ACS反馈参数") - private String resultParam; - - @Schema(description = "备注", example = "你说的对") - @ExcelProperty("备注") - private String remark; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("创建时间") - private LocalDateTime createTime; - -} \ No newline at end of file +package cn.code.nl.module.task.controller.admin.transporttask.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import cn.idev.excel.annotation.*; +import cn.code.nl.framework.excel.core.annotations.DictFormat; +import cn.code.nl.framework.excel.core.convert.DictConvert; + +@Schema(description = "管理后台 - 搬运任务 Response VO") +@Data +@ExcelIgnoreUnannotated +public class TransportTaskRespVO { + + @Schema(description = "任务标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "11528") + @ExcelProperty("任务标识") + private Long taskId; + + @Schema(description = "任务编码", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("任务编码") + private String taskCode; + + @Schema(description = "任务名称", example = "张三") + @ExcelProperty("任务名称") + private String taskName; + + @Schema(description = "业务归属服务:LMS/WMS,用于完成取消事件一级路由", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("业务归属服务:LMS/WMS,用于完成取消事件一级路由") + private String ownerService; + + @Schema(description = "业务类型", example = "2") + @ExcelProperty("业务类型") + private String bizType; + + @Schema(description = "业务侧标识", example = "31008") + @ExcelProperty("业务侧标识") + private String bizId; + + @Schema(description = "业务回调处理器编码") + @ExcelProperty("业务回调处理器编码") + private String handleCode; + + @Schema(description = "任务类型", example = "2") + @ExcelProperty("任务类型") + private String taskType; + + @Schema(description = "任务状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("任务状态") + private String taskStatus; + + @Schema(description = "ACS任务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("ACS任务类型") + private String acsTaskType; + + @Schema(description = "AGV系统类型", example = "1") + @ExcelProperty("AGV系统类型") + private String agvSystemType; + + @Schema(description = "ACS外部任务号") + @ExcelProperty("ACS外部任务号") + private String externalTaskNo; + + @Schema(description = "取货点1") + @ExcelProperty("取货点1") + private String pointCode1; + + @Schema(description = "放货点1") + @ExcelProperty("放货点1") + private String pointCode2; + + @Schema(description = "取货点2") + @ExcelProperty("取货点2") + private String pointCode3; + + @Schema(description = "放货点2") + @ExcelProperty("放货点2") + private String pointCode4; + + @Schema(description = "载具类型", example = "2") + @ExcelProperty("载具类型") + private String vehicleType; + + @Schema(description = "载具数量", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("载具数量") + private Long vehicleQty; + + @Schema(description = "载具编码") + @ExcelProperty("载具编码") + private String vehicleCode; + + @Schema(description = "载具编码2") + @ExcelProperty("载具编码2") + private String vehicleCode2; + + @Schema(description = "车号") + @ExcelProperty("车号") + private String carNo; + + @Schema(description = "优先级", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("优先级") + private String priority; + + @Schema(description = "生产区域") + @ExcelProperty("生产区域") + private String productArea; + + @Schema(description = "是否自动下发", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("是否自动下发") + private String isAutoIssue; + + @Schema(description = "任务组标识", example = "21169") + @ExcelProperty("任务组标识") + private Long taskGroupId; + + @Schema(description = "任务组顺序号", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("任务组顺序号") + private Long sortSeq; + + @Schema(description = "任务完成类型", example = "1") + @ExcelProperty("任务完成类型") + private String finishedType; + + @Schema(description = "业务回调状态:PENDING/SUCCESS/FAILED", example = "2") + @ExcelProperty("业务回调状态:PENDING/SUCCESS/FAILED") + private String callbackStatus; + + @Schema(description = "业务回调重试次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "2146") + @ExcelProperty("业务回调重试次数") + private Integer callbackRetryCount; + + @Schema(description = "业务回调失败原因") + @ExcelProperty("业务回调失败原因") + private String callbackErrorMsg; + + @Schema(description = "生成方式", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty(value = "生成方式", converter = DictConvert.class) + @DictFormat("task_create_mode") + private String createMode; + + @Schema(description = "创建任务请求参数") + @ExcelProperty("创建任务请求参数") + private String requestParam; + + @Schema(description = "下发ACS的AcsTaskDto扩展报文") + @ExcelProperty("下发ACS的AcsTaskDto扩展报文") + private String dispatchParam; + + @Schema(description = "ACS反馈参数") + @ExcelProperty("ACS反馈参数") + private String resultParam; + + @Schema(description = "备注", example = "你说的对") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/dal/mysql/transporttask/TransportTaskMapper.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/dal/mysql/transporttask/TransportTaskMapper.java index 5e52125a..ee41978a 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/dal/mysql/transporttask/TransportTaskMapper.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/dal/mysql/transporttask/TransportTaskMapper.java @@ -27,7 +27,7 @@ public interface TransportTaskMapper extends BaseMapperX { .eqIfPresent(TransportTaskDO::getBizType, reqVO.getBizType()) .eqIfPresent(TransportTaskDO::getBizId, reqVO.getBizId()) .eqIfPresent(TransportTaskDO::getHandleCode, reqVO.getHandleCode()) - .eqIfPresent(TransportTaskDO::getTaskType, reqVO.getTaskType()) + .inIfPresent(TransportTaskDO::getTaskType, reqVO.getTaskTypeList()) .inIfPresent(TransportTaskDO::getTaskStatus, reqVO.getTaskStatus()) .eqIfPresent(TransportTaskDO::getAcsTaskType, reqVO.getAcsTaskType()) .eqIfPresent(TransportTaskDO::getAgvSystemType, reqVO.getAgvSystemType()) diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskService.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskService.java index 5e46ec7d..f7f4c717 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskService.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskService.java @@ -76,6 +76,13 @@ public interface TransportTaskService { */ void operateTransportTask(@Valid TransportTaskOperateReqVO reqVO); + /** + * 根据任务ID下发搬运任务到 ACS + * + * @param taskId 任务ID + */ + void issueTransportTask(Long taskId); + /** * 根据 taskId 查询任务全量信息(RPC 用,自动过滤逻辑删除,查不到返回 null) * diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskServiceImpl.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskServiceImpl.java index 3b687f7d..678f4710 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskServiceImpl.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskServiceImpl.java @@ -2,6 +2,7 @@ package cn.code.nl.module.task.service.transporttask; import cn.code.nl.framework.common.pojo.PageResult; import cn.code.nl.framework.common.util.object.BeanUtils; +import cn.code.nl.module.base.api.classstandard.ClassStandardApi; import cn.code.nl.module.task.controller.admin.transporttask.vo.TransportTaskOperateReqVO; import cn.code.nl.module.task.controller.admin.transporttask.vo.TransportTaskPageReqVO; import cn.code.nl.module.task.controller.admin.transporttask.vo.TransportTaskSaveReqVO; @@ -19,6 +20,7 @@ import cn.code.nl.module.task.manage.TransportTaskIssueManager; import cn.code.nl.module.task.manage.TransportTaskOperateCheckManager; import cn.code.nl.module.task.manage.TransportTaskOperationManager; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -29,8 +31,10 @@ import java.util.List; import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.code.nl.module.task.enums.ErrorCodeConstants.TRANSPORT_TASK_ALREADY_FINAL; +import static cn.code.nl.module.task.enums.ErrorCodeConstants.TRANSPORT_TASK_AUTO_ISSUE_NOT_ALLOW_MANUAL; import static cn.code.nl.module.task.enums.ErrorCodeConstants.TRANSPORT_TASK_NOT_EXISTS; import static cn.code.nl.module.task.enums.ErrorCodeConstants.TRANSPORT_TASK_OPERATION_NOT_SUPPORTED; +import static cn.code.nl.module.task.enums.ErrorCodeConstants.TRANSPORT_TASK_STATUS_NOT_ALLOW; /** * 搬运任务 Service 实现类 @@ -54,6 +58,9 @@ public class TransportTaskServiceImpl implements TransportTaskService { @Resource private TransportTaskOperateCheckManager transportTaskOperateCheckManager; + @Resource + private ClassStandardApi classStandardApi; + @Override public Long createTransportTask(TransportTaskSaveReqVO createReqVO) { TransportTaskDO transportTask = BeanUtils.toBean(createReqVO, TransportTaskDO.class); @@ -111,6 +118,10 @@ public class TransportTaskServiceImpl implements TransportTaskService { @Override public PageResult getTransportTaskPage(TransportTaskPageReqVO pageReqVO) { + if (StrUtil.isNotBlank(pageReqVO.getTaskType())) { + List taskTypeList = classStandardApi.getClassStandardCodeListByCode(pageReqVO.getTaskType()).getCheckedData(); + pageReqVO.setTaskTypeList(CollUtil.isNotEmpty(taskTypeList) ? taskTypeList : List.of(pageReqVO.getTaskType())); + } return transportTaskMapper.selectPage(pageReqVO); } @@ -148,6 +159,23 @@ public class TransportTaskServiceImpl implements TransportTaskService { transportTaskOperationManager.dispatchOperation(task, type, reqDTO); } + /** + * 根据任务ID手动下发任务到 ACS,复用自动下发的数组接口逻辑 + * + * @param taskId 任务ID + */ + @Override + public void issueTransportTask(Long taskId) { + TransportTaskDO task = transportTaskMapper.selectById(taskId); + if (task == null) { + throw exception(TRANSPORT_TASK_NOT_EXISTS); + } + if ("1".equals(task.getIsAutoIssue())) { + throw exception(TRANSPORT_TASK_AUTO_ISSUE_NOT_ALLOW_MANUAL); + } + transportTaskIssueManager.issueTasks(List.of(task)); + } + @Override public TaskInfoDTO getTaskInfoById(Long taskId) { TransportTaskDO task = transportTaskMapper.selectById(taskId); diff --git a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/task/transporttask/index.ts b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/task/transporttask/index.ts index 324cda8b..3edc4346 100644 --- a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/task/transporttask/index.ts +++ b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/task/transporttask/index.ts @@ -93,4 +93,8 @@ export function operateTransportTask(data: { return requestClient.post('/task/transport-task/operate', data); } +/** PC 端下发搬运任务到 ACS */ +export function issueTransportTask(taskId: number | string) { + return requestClient.post(`/task/transport-task/issue?taskId=${taskId}`); +} diff --git a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/base/materialbase/data.ts b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/base/materialbase/data.ts index 0937d1bd..79a612ff 100644 --- a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/base/materialbase/data.ts +++ b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/base/materialbase/data.ts @@ -1,12 +1,12 @@ -import type { VbenFormSchema } from '#/adapter/form'; -import type { VxeTableGridOptions } from '#/adapter/vxe-table'; -import type { BaseMaterialBaseApi } from '#/api/base/materialbase'; +import type {VbenFormSchema} from '#/adapter/form'; +import type {VxeTableGridOptions} from '#/adapter/vxe-table'; +import type {BaseMaterialBaseApi} from '#/api/base/materialbase'; -import { handleTree } from '@vben/utils'; +import {handleTree} from '@vben/utils'; -import { getClassStandardList, getClassStandardListByCode } from '#/api/base/classstandard'; -import { getSimpleMeasureUnitList } from '#/api/base/measureunit'; -import { getRangePickerDefaultProps } from '#/utils'; +import {getClassStandardList, getClassStandardListByCode} from '#/api/base/classstandard'; +import {getSimpleMeasureUnitList} from '#/api/base/measureunit'; +import {getRangePickerDefaultProps} from '#/utils'; // ========== 分类映射:classId → className ========== const classNameMap: Record = {}; @@ -46,102 +46,218 @@ async function loadMeasureUnitList() { // ========== 新增/修改的表单 ========== export function useFormSchema(): VbenFormSchema[] { return [ - { fieldName: 'materialId', component: 'Input', dependencies: { triggerFields: [''], show: () => false } }, - { fieldName: 'materialCode', label: '物料编码', rules: 'required', component: 'Input', componentProps: { placeholder: '请输入物料编码' } }, - { fieldName: 'materialName', label: '物料名称', rules: 'required', component: 'Input', componentProps: { placeholder: '请输入物料名称' } }, - { fieldName: 'materialSpec', label: '规格', component: 'Input', componentProps: { placeholder: '请输入规格' } }, - { fieldName: 'materialModel', label: '型号', component: 'Input', componentProps: { placeholder: '请输入型号' } }, - { fieldName: 'englishName', label: '外文名称', component: 'Input', componentProps: { placeholder: '请输入外文名称' } }, + { + fieldName: 'materialId', + component: 'Input', + dependencies: {triggerFields: [''], show: () => false} + }, + { + fieldName: 'materialCode', + label: '物料编码', + rules: 'required', + component: 'Input', + componentProps: {placeholder: '请输入物料编码'} + }, + { + fieldName: 'materialName', + label: '物料名称', + rules: 'required', + component: 'Input', + componentProps: {placeholder: '请输入物料名称'} + }, + { + fieldName: 'materialSpec', + label: '规格', + component: 'Input', + componentProps: {placeholder: '请输入规格'} + }, + { + fieldName: 'materialModel', + label: '型号', + component: 'Input', + componentProps: {placeholder: '请输入型号'} + }, + { + fieldName: 'englishName', + label: '外文名称', + component: 'Input', + componentProps: {placeholder: '请输入外文名称'} + }, { fieldName: 'materialTypeId', label: '物料分类', component: 'ApiTreeSelect', - componentProps: { api: loadMaterialTypeTree, labelField: 'className', valueField: 'classId', childrenField: 'children', placeholder: '请选择物料分类', allowClear: true, treeDefaultExpandAll: true }, + componentProps: { + api: loadMaterialTypeTree, + labelField: 'className', + valueField: 'classId', + childrenField: 'children', + placeholder: '请选择物料分类', + allowClear: true, + treeDefaultExpandAll: true + }, }, { fieldName: 'baseUnitId', label: '基本计量单位', rules: 'required', component: 'ApiSelect', - componentProps: { api: loadMeasureUnitList, labelField: 'unitCode', valueField: 'measureUnitId', placeholder: '请选择基本计量单位', allowClear: true }, + componentProps: { + api: loadMeasureUnitList, + labelField: 'unitCode', + valueField: 'measureUnitId', + placeholder: '请选择基本计量单位', + allowClear: true + }, }, { fieldName: 'assUnitId', label: '辅助计量单位', component: 'ApiSelect', - componentProps: { api: loadMeasureUnitList, labelField: 'unitCode', valueField: 'measureUnitId', placeholder: '请选择辅助计量单位', allowClear: true }, + componentProps: { + api: loadMeasureUnitList, + labelField: 'unitCode', + valueField: 'measureUnitId', + placeholder: '请选择辅助计量单位', + allowClear: true + }, }, { fieldName: 'lenUnitId', label: '长度单位', component: 'ApiSelect', - componentProps: { api: loadMeasureUnitList, labelField: 'unitCode', valueField: 'measureUnitId', placeholder: '请选择长度单位', allowClear: true }, + componentProps: { + api: loadMeasureUnitList, + labelField: 'unitCode', + valueField: 'measureUnitId', + placeholder: '请选择长度单位', + allowClear: true + }, }, { fieldName: 'weightUnitId', label: '重量单位', component: 'ApiSelect', - componentProps: { api: loadMeasureUnitList, labelField: 'unitCode', valueField: 'measureUnitId', placeholder: '请选择重量单位', allowClear: true }, + componentProps: { + api: loadMeasureUnitList, + labelField: 'unitCode', + valueField: 'measureUnitId', + placeholder: '请选择重量单位', + allowClear: true + }, }, { fieldName: 'cubageUnitId', label: '体积单位', component: 'ApiSelect', - componentProps: { api: loadMeasureUnitList, labelField: 'unitCode', valueField: 'measureUnitId', placeholder: '请选择体积单位', allowClear: true }, + componentProps: { + api: loadMeasureUnitList, + labelField: 'unitCode', + valueField: 'measureUnitId', + placeholder: '请选择体积单位', + allowClear: true + }, }, { fieldName: 'isUsed', label: '是否启用', rules: 'required', component: 'RadioGroup', - componentProps: { options: [{ label: '是', value: '1' }, { label: '否', value: '0' }], buttonStyle: 'solid', optionType: 'button' }, + componentProps: { + options: [{label: '是', value: '1'}, {label: '否', value: '0'}], + buttonStyle: 'solid', + optionType: 'button' + }, + }, + { + fieldName: 'extId', + label: '外部标识', + component: 'Input', + componentProps: {placeholder: '请输入外部标识'} }, - { fieldName: 'extId', label: '外部标识', component: 'Input', componentProps: { placeholder: '请输入外部标识' } }, ]; } // ========== 列表的搜索表单 ========== export function useGridFormSchema(): VbenFormSchema[] { return [ - { fieldName: 'materialCode', label: '物料编码', component: 'Input', componentProps: { allowClear: true, placeholder: '请输入物料编码' } }, - { fieldName: 'materialName', label: '物料名称', component: 'Input', componentProps: { allowClear: true, placeholder: '请输入物料名称' } }, + { + fieldName: 'materialCode', + label: '物料编码', + component: 'Input', + componentProps: {allowClear: true, placeholder: '请输入物料编码'} + }, + { + fieldName: 'materialName', + label: '物料名称', + component: 'Input', + componentProps: {allowClear: true, placeholder: '请输入物料名称'} + }, { fieldName: 'materialTypeId', label: '物料分类', component: 'ApiTreeSelect', - componentProps: { api: loadMaterialTypeTree, labelField: 'className', valueField: 'classId', childrenField: 'children', placeholder: '请选择物料分类', allowClear: true }, + componentProps: { + api: loadMaterialTypeTree, + labelField: 'className', + valueField: 'classId', + childrenField: 'children', + placeholder: '请选择物料分类', + allowClear: true + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: {...getRangePickerDefaultProps(), allowClear: true} + }, + { + fieldName: 'isUsed', + label: '是否启用', + component: 'Select', + componentProps: { + allowClear: true, + placeholder: '请选择', + options: [{label: '是', value: '1'}, {label: '否', value: '0'}] + } }, - { fieldName: 'createTime', label: '创建时间', component: 'RangePicker', componentProps: { ...getRangePickerDefaultProps(), allowClear: true } }, - { fieldName: 'isUsed', label: '是否启用', component: 'Select', componentProps: { allowClear: true, placeholder: '请选择', options: [{ label: '是', value: '1' }, { label: '否', value: '0' }] } }, ]; } // ========== 列表的字段 ========== export function useGridColumns(): VxeTableGridOptions['columns'] { return [ - { type: 'checkbox', width: 40 }, - { field: 'materialCode', title: '物料编码', minWidth: 120 }, - { field: 'materialName', title: '物料名称', minWidth: 200 }, - { field: 'materialSpec', title: '规格', minWidth: 120 }, - { field: 'materialModel', title: '型号', minWidth: 120 }, - { field: 'englishName', title: '外文名称', minWidth: 120 }, + {type: 'checkbox', width: 40}, + {field: 'materialCode', title: '物料编码', minWidth: 120}, + {field: 'materialName', title: '物料名称', minWidth: 200}, + {field: 'materialSpec', title: '规格', minWidth: 120}, + {field: 'materialModel', title: '型号', minWidth: 120}, + {field: 'englishName', title: '外文名称', minWidth: 120}, { field: 'materialTypeId', title: '物料分类', minWidth: 150, - formatter: ({ cellValue }: { cellValue: number }) => classNameMap[cellValue] || cellValue || '-', + formatter: ({cellValue}: { + cellValue: number + }) => classNameMap[cellValue] || cellValue || '-', }, { field: 'baseUnitId', title: '基本计量单位', minWidth: 120, - formatter: ({ cellValue }: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-', + formatter: ({cellValue}: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-', }, { field: 'assUnitId', title: '辅助计量单位', minWidth: 120, - formatter: ({ cellValue }: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-', + formatter: ({cellValue}: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-', }, { field: 'lenUnitId', title: '长度单位', minWidth: 120, - formatter: ({ cellValue }: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-', + formatter: ({cellValue}: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-', }, { field: 'weightUnitId', title: '重量单位', minWidth: 120, - formatter: ({ cellValue }: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-', + formatter: ({cellValue}: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-', }, { field: 'cubageUnitId', title: '体积单位', minWidth: 120, - formatter: ({ cellValue }: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-', + formatter: ({cellValue}: { cellValue: number }) => unitCodeMap[cellValue] || cellValue || '-', }, - { field: 'createTime', title: '创建时间', minWidth: 180, formatter: 'formatDateTime' }, - { field: 'isUsed', title: '是否启用', minWidth: 100, formatter: ({ cellValue }: { cellValue: string }) => (cellValue === '1' ? '是' : '否') }, - { field: 'extId', title: '外部标识', minWidth: 120 }, - { title: '操作', width: 200, fixed: 'right', slots: { default: 'actions' } }, + {field: 'createTime', title: '创建时间', minWidth: 180, formatter: 'formatDateTime'}, + { + field: 'isUsed', + title: '是否启用', + minWidth: 100, + formatter: ({cellValue}: { cellValue: string }) => (cellValue === '1' ? '是' : '否') + }, + {field: 'extId', title: '外部标识', minWidth: 120}, + {title: '操作', width: 200, fixed: 'right', slots: {default: 'actions'}}, ]; } diff --git a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/task/transporttask/data.ts b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/task/transporttask/data.ts index da5443dd..8032b1bb 100644 --- a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/task/transporttask/data.ts +++ b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/task/transporttask/data.ts @@ -4,12 +4,31 @@ import type { TaskTransportTaskApi } from '#/api/task/transporttask'; import { DICT_TYPE } from '@vben/constants'; import { getDictOptions } from '@vben/hooks'; +import { handleTree } from '@vben/utils'; import dayjs from 'dayjs'; +import { getClassStandardListByCode } from '#/api/base/classstandard'; import { getRangePickerDefaultProps } from '#/utils'; +const taskTypeNameMap: Record = {}; + +async function loadTaskTypeTree() { + const data = await getClassStandardListByCode('0002'); + if (!data || data.length === 0) return []; + return handleTree(data, 'classId', 'parentClassId'); +} + /** 新增/修改的表单 */ +export async function loadAllLookupData() { + const taskTypeData = await getClassStandardListByCode('0002'); + taskTypeData?.forEach((item) => { + if (item.classCode) { + taskTypeNameMap[item.classCode] = item.className; + } + }); +} + export function useFormSchema(): VbenFormSchema[] { return [ { @@ -369,11 +388,15 @@ export function useGridFormSchema(): VbenFormSchema[] { { fieldName: 'taskType', label: '任务类型', - component: 'Select', + component: 'ApiTreeSelect', componentProps: { allowClear: true, - options: [], + api: loadTaskTypeTree, + childrenField: 'children', + labelField: 'className', placeholder: '请选择任务类型', + treeDefaultExpandAll: true, + valueField: 'classCode', }, }, { @@ -588,6 +611,8 @@ export function useGridColumns(): VxeTableGridOptions + taskTypeNameMap[cellValue] || cellValue || '-', }, { field: 'acsTaskType', @@ -608,6 +633,10 @@ export function useGridColumns(): VxeTableGridOptions { + await loadAllLookupData(); + ready.value = true; +}); + const [FormModal, formModalApi] = useVbenModal({ connectedComponent: Form, destroyOnClose: true, @@ -57,6 +64,22 @@ async function handleOperate( } } +/** PC 端下发搬运任务到 ACS */ +async function handleIssue(row: TaskTransportTaskApi.TransportTask) { + await confirm(`确认要下发【${row.taskCode}】到 ACS 吗?`); + const hideLoading = message.loading({ + content: '正在下发...', + duration: 0, + }); + try { + await issueTransportTask(row.taskId!); + message.success('下发成功'); + handleRefresh(); + } finally { + hideLoading(); + } +} + /** 删除搬运任务 */ async function handleDelete(row: TaskTransportTaskApi.TransportTask) { const hideLoading = message.loading({ @@ -141,7 +164,7 @@ const [Grid, gridApi] = useVbenVxeGrid({