From ea83eb9eebbf3ea2823b6f377f913a967013d938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=ABUmbrella?= <2539020564@qq.com> Date: Thu, 5 Mar 2026 18:10:58 +0800 Subject: [PATCH] =?UTF-8?q?1.=E7=89=A9=E6=96=99=E8=A1=A8=E5=88=86=E9=A1=B5?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=202.=E5=BA=93=E4=BD=8D=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E8=A1=A8=E6=98=8E=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../logistics/OrderBoxRefinement.java | 23 +++ .../AGVCallBackDto.java} | 4 +- .../BoxBindingDto.java} | 5 +- .../desk/logistics/pojo/dto/TaskDto.java | 57 ++++++ .../pojo/entity/TaskExecuteRecord.java | 2 +- .../desk/logistics/pojo/vo/TaskVO.java | 25 +++ .../controller/AGVDockingController.java | 5 +- .../controller/OrderBoxController.java | 36 +++- .../desk/logistics/mapper/TaskMapper.java | 16 ++ .../desk/logistics/mapper/TaskMapper.xml | 31 +++ .../logistics/service/IOrderBoxService.java | 4 +- .../service/ITaskExecuteRecordService.java | 6 +- .../desk/logistics/service/ITaskService.java | 5 + .../service/impl/IOrderBoxServiceImpl.java | 9 +- .../impl/StorageMonitoringServiceImpl.java | 191 +++++++++++++++--- .../impl/TaskExecuteRecordServiceImpl.java | 113 +++++++---- .../service/impl/TaskServiceImpl.java | 10 + 17 files changed, 455 insertions(+), 87 deletions(-) create mode 100644 blade-ops/blade-job/src/main/java/org/springblade/job/processor/logistics/OrderBoxRefinement.java rename blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/{entity/AGVCallBack.java => dto/AGVCallBackDto.java} (93%) rename blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/{entity/BoxBinding.java => dto/BoxBindingDto.java} (69%) create mode 100644 blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/TaskDto.java create mode 100644 blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/vo/TaskVO.java diff --git a/blade-ops/blade-job/src/main/java/org/springblade/job/processor/logistics/OrderBoxRefinement.java b/blade-ops/blade-job/src/main/java/org/springblade/job/processor/logistics/OrderBoxRefinement.java new file mode 100644 index 00000000..69c4975d --- /dev/null +++ b/blade-ops/blade-job/src/main/java/org/springblade/job/processor/logistics/OrderBoxRefinement.java @@ -0,0 +1,23 @@ +package org.springblade.job.processor.logistics; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import tech.powerjob.worker.core.processor.ProcessResult; +import tech.powerjob.worker.core.processor.TaskContext; +import tech.powerjob.worker.core.processor.sdk.BasicProcessor; + +/** + * 物流订单绑定模块 + */ +@Component +@Data +@Slf4j +public class OrderBoxRefinement implements BasicProcessor { + @Override + public ProcessResult process(TaskContext taskContext) throws Exception { + System.out.println("hello world"); + log.info("hello world"); + return new ProcessResult(true); + } +} diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/AGVCallBack.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/AGVCallBackDto.java similarity index 93% rename from blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/AGVCallBack.java rename to blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/AGVCallBackDto.java index 0d08ede8..c7758e62 100644 --- a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/AGVCallBack.java +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/AGVCallBackDto.java @@ -1,11 +1,11 @@ -package org.springblade.desk.logistics.pojo.entity; +package org.springblade.desk.logistics.pojo.dto; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @Data @Schema(description = "箱绑定接收") -public class AGVCallBack { +public class AGVCallBackDto { /** * 请求编号,每个请求都要一个唯一 * 编号, 同一个请求重复提交, 使 diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/BoxBinding.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/BoxBindingDto.java similarity index 69% rename from blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/BoxBinding.java rename to blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/BoxBindingDto.java index c82c5ed5..f7c4712f 100644 --- a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/BoxBinding.java +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/BoxBindingDto.java @@ -1,14 +1,13 @@ -package org.springblade.desk.logistics.pojo.entity; +package org.springblade.desk.logistics.pojo.dto; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; import java.util.ArrayList; @Data @Schema(description = "箱绑定接收表") -public class BoxBinding { +public class BoxBindingDto { private String boxBarcode; private ArrayList orderIdList; private Long wcId; diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/TaskDto.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/TaskDto.java new file mode 100644 index 00000000..fffc4570 --- /dev/null +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/dto/TaskDto.java @@ -0,0 +1,57 @@ +package org.springblade.desk.logistics.pojo.dto; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springblade.core.mp.base.BaseEntity; + +import java.io.Serial; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 物流任务实体类 + * + * @author: liweidong + * @create: 2026-03-03 + */ +@Data +@Schema(description = "物流任务对象") + +public class TaskDto extends BaseEntity { + + /** + * 箱条码 + */ + @Schema(description = "箱条码") + private String boxBarcode; + + /** + * 站点ID + */ + @Schema(description = "站点ID") + private Long stationId; + + /** + * 作业中心ID + */ + @Schema(description = "作业中心ID") + private Long wcId; + /** + * 当前状态 0:退回(超重) 1:站点 2:库位 3:等待 4:回库 5:结束 + */ + @Schema(description = "当前状态 0:退回(超重) 1:站点 2:库位 3:等待 4:回库 5:结束") + private Integer taskStatus; + /** + * 开始时间 + */ + @Schema(description = "开始时间") + private Date startTime; + /** + * 结束时间 + */ + @Schema(description = "结束时间") + private Date endTime; + + +} diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/TaskExecuteRecord.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/TaskExecuteRecord.java index f138f560..40b450f2 100644 --- a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/TaskExecuteRecord.java +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/entity/TaskExecuteRecord.java @@ -35,7 +35,7 @@ public class TaskExecuteRecord extends BaseEntity { public static final String STATUS_START = "start"; /** - * 状态常量:走出储位 + * 状态常量:结束 */ public static final String STATUS_END = "end"; diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/vo/TaskVO.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/vo/TaskVO.java new file mode 100644 index 00000000..f808ee7f --- /dev/null +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/logistics/pojo/vo/TaskVO.java @@ -0,0 +1,25 @@ +package org.springblade.desk.logistics.pojo.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springblade.desk.device.pojo.entity.EquipmentEntity; +import org.springblade.desk.logistics.pojo.entity.Task; + +import java.io.Serial; +@Data +@EqualsAndHashCode(callSuper = true) +public class TaskVO extends Task { + @Serial + private static final long serialVersionUID = 1L; + /** + * 主键ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + /** + * 状态名称 + */ +// String statusName; +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/AGVDockingController.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/AGVDockingController.java index e765fe39..83f32964 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/AGVDockingController.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/AGVDockingController.java @@ -5,7 +5,8 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; import org.springblade.core.tool.api.R; -import org.springblade.desk.logistics.pojo.entity.AGVCallBack; + +import org.springblade.desk.logistics.pojo.dto.AGVCallBackDto; import org.springblade.desk.logistics.service.IOrderBoxService; import org.springblade.desk.logistics.service.ITaskExecuteRecordService; import org.springframework.web.bind.annotation.PostMapping; @@ -34,7 +35,7 @@ public class AGVDockingController { summary = "agv小车回调接口", description = "AGV小车回调接口" ) - public R agvCallback(@RequestBody AGVCallBack agvCallBack ){ + public R agvCallback(@RequestBody AGVCallBackDto agvCallBack ){ // 1.参数合法性校验 if (agvCallBack == null || agvCallBack.getTaskCode().trim().isEmpty()) { return R.fail("任务单号不能为空"); diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBoxController.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBoxController.java index 363d3990..37acc733 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBoxController.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/controller/OrderBoxController.java @@ -1,22 +1,31 @@ package org.springblade.desk.logistics.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; import org.springblade.core.boot.ctrl.BladeController; +import org.springblade.core.mp.support.Condition; +import org.springblade.core.mp.support.Query; import org.springblade.core.tool.api.R; import org.springblade.desk.dashboard.pojo.entity.BsWorkCenterEntity; import org.springblade.desk.dashboard.service.IBsWorkCenterService; -import org.springblade.desk.dashboard.wrapper.BsWorkCenterWrapper; -import org.springblade.desk.logistics.pojo.entity.BoxBinding; +import org.springblade.desk.device.pojo.entity.EquipmentEntity; +import org.springblade.desk.device.pojo.vo.EquipmentVO; +import org.springblade.desk.logistics.pojo.dto.BoxBindingDto; +import org.springblade.desk.logistics.pojo.dto.TaskDto; +import org.springblade.desk.logistics.pojo.vo.TaskVO; import org.springblade.desk.logistics.service.IOrderBoxService; +import org.springblade.desk.logistics.service.ITaskService; import org.springframework.web.bind.annotation.*; import java.math.BigDecimal; -import java.util.List; /** * 订单箱子 控制器 @@ -31,6 +40,7 @@ import java.util.List; public class OrderBoxController extends BladeController { private final IOrderBoxService iOrderBoxService; private final IBsWorkCenterService bsWorkCenterService; + private final ITaskService taskService; @PostMapping("/getWeighing") @@ -70,7 +80,7 @@ public class OrderBoxController extends BladeController { summary = "绑定箱条码和订单", description = "绑定箱条码和订单信息内容" ) - public R boxBinding(@RequestBody BoxBinding boxBinding){ + public R boxBinding(@RequestBody BoxBindingDto boxBinding){ // 1.参数合法性校验 if (boxBinding == null || boxBinding.getBoxBarcode().trim().isEmpty()) { return R.fail("箱条码不能为空"); @@ -81,6 +91,24 @@ public class OrderBoxController extends BladeController { return iOrderBoxService.boxBinding(boxBinding); } + /** + * 任务表 自定义分页 + */ + @GetMapping("/page") + @ApiOperationSupport(order = 4) + @Operation(summary = "分页", description = "") + @Parameters({ + @Parameter(name = "boxBarcode", description = "箱条码", in = ParameterIn.QUERY, schema = @Schema(type = "String")), + @Parameter(name = "stationId", description = "站点ID", in = ParameterIn.QUERY, schema = @Schema(type = "Long")), + @Parameter(name = "wcId", description = "作业中心ID", in = ParameterIn.QUERY, schema = @Schema(type = "Long")), + @Parameter(name = "taskStatus", description = "当前状态 0:退回(超重) 1:站点 2:库位 3:等待 4:回库 5:结束", in = ParameterIn.QUERY, schema = @Schema(type = "Integer")), + @Parameter(name = "startTime", description = "开始时间", in = ParameterIn.QUERY, schema = @Schema(type = "Date")), + @Parameter(name = "endTime", description = "结束时间", in = ParameterIn.QUERY, schema = @Schema(type = "Date")) + }) + public R> page(@Parameter(hidden = true) TaskDto taskDto, Query query) { + IPage pages = taskService.selectPage(Condition.getPage(query), taskDto); + return R.data(pages); + } } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/TaskMapper.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/TaskMapper.java index 16122207..3fab30f4 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/TaskMapper.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/TaskMapper.java @@ -1,10 +1,26 @@ package org.springblade.desk.logistics.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; import org.apache.ibatis.annotations.Param; +import org.springblade.desk.device.pojo.entity.EquipmentEntity; +import org.springblade.desk.device.pojo.vo.EquipmentVO; +import org.springblade.desk.logistics.pojo.dto.TaskDto; import org.springblade.desk.logistics.pojo.entity.Task; import org.springblade.desk.logistics.pojo.entity.WeighData; +import org.springblade.desk.logistics.pojo.vo.TaskVO; + +import java.util.List; + public interface TaskMapper extends BaseMapper { Task selectByBoxBarcode(@Param("boxBarcode") String boxBarcode); + /** + * 自定义分页 + * + * @param page 分页参数 + * @param taskDto 查询参数 + * @return List + */ + List selectEquipmentPage(IPage page, TaskDto taskDto); } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/TaskMapper.xml b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/TaskMapper.xml index 635ac486..12e3e6a9 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/TaskMapper.xml +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/mapper/TaskMapper.xml @@ -12,4 +12,35 @@ AND BOX_BARCODE = #{boxBarcode} AND TASK_STATUS NOT IN (2, 9); + + diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IOrderBoxService.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IOrderBoxService.java index 2987a5ce..4af6129e 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IOrderBoxService.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/IOrderBoxService.java @@ -1,7 +1,7 @@ package org.springblade.desk.logistics.service; import org.springblade.core.tool.api.R; -import org.springblade.desk.logistics.pojo.entity.BoxBinding; +import org.springblade.desk.logistics.pojo.dto.BoxBindingDto; import java.math.BigDecimal; @@ -35,7 +35,7 @@ public interface IOrderBoxService { * - 成功:R.success(),携带绑定成功的提示或绑定记录数 * - 失败:R.fail(),携带失败原因(如箱条码不存在、订单已绑定、唯一约束冲突等) */ - R boxBinding(BoxBinding boxBinding); + R boxBinding(BoxBindingDto boxBinding); /** * 箱条码与订单解绑 diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/ITaskExecuteRecordService.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/ITaskExecuteRecordService.java index f5505048..b86a4025 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/ITaskExecuteRecordService.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/ITaskExecuteRecordService.java @@ -27,8 +27,8 @@ package org.springblade.desk.logistics.service; import org.springblade.core.mp.base.BaseService; import org.springblade.core.tool.api.R; -import org.springblade.desk.logistics.pojo.entity.AGVCallBack; -import org.springblade.desk.logistics.pojo.entity.OrderBind; +import org.springblade.desk.logistics.pojo.dto.AGVCallBackDto; + import org.springblade.desk.logistics.pojo.entity.TaskExecuteRecord; /** @@ -39,5 +39,5 @@ import org.springblade.desk.logistics.pojo.entity.TaskExecuteRecord; */ public interface ITaskExecuteRecordService extends BaseService { - R agvCallback(AGVCallBack agvCallBack); + R agvCallback(AGVCallBackDto agvCallBack); } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/ITaskService.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/ITaskService.java index 9c590e1b..285765c0 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/ITaskService.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/ITaskService.java @@ -25,8 +25,11 @@ */ package org.springblade.desk.logistics.service; +import com.baomidou.mybatisplus.core.metadata.IPage; import org.springblade.core.mp.base.BaseService; +import org.springblade.desk.logistics.pojo.dto.TaskDto; import org.springblade.desk.logistics.pojo.entity.Task; +import org.springblade.desk.logistics.pojo.vo.TaskVO; import java.math.BigDecimal; @@ -52,4 +55,6 @@ public interface ITaskService extends BaseService { * @return */ Task getBoxBarcode(String boxBarcode); + + IPage selectPage(IPage page, TaskDto taskDto); } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/IOrderBoxServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/IOrderBoxServiceImpl.java index 9a6d621d..0abe20fc 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/IOrderBoxServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/IOrderBoxServiceImpl.java @@ -5,11 +5,11 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import lombok.extern.slf4j.Slf4j; import org.springblade.core.secure.utils.AuthUtil; import org.springblade.core.tool.api.R; +import org.springblade.desk.logistics.pojo.dto.BoxBindingDto; import org.springblade.desk.logistics.pojo.entity.*; import org.springblade.desk.logistics.service.*; import org.springblade.desk.order.pojo.entity.YieldOrder; import org.springblade.desk.order.service.IYieldOrderService; -import org.springblade.system.pojo.entity.AuthClient; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -19,7 +19,6 @@ import java.util.stream.Collectors; import static org.springblade.desk.logistics.pojo.entity.OrderBind.STATUS_UNBINDED; import static org.springblade.desk.logistics.pojo.entity.Station.STATUS_OCCUPIED; -import static org.springblade.desk.logistics.pojo.entity.Task.STATUS_FINISHED; /** * 订单箱业务实现类 @@ -120,7 +119,7 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { * - 失败:R.fail(),携带具体失败原因(如参数为空、订单已绑定、重量超限等) */ @Override - public R boxBinding(BoxBinding boxBinding) { + public R boxBinding(BoxBindingDto boxBinding) { log.info("接收到箱绑定实际参数:{}", boxBinding); // 1. 入参非空校验(基础防护) @@ -309,12 +308,12 @@ public class IOrderBoxServiceImpl implements IOrderBoxService { } // 2. 站点无可用则查询可用库位(状态为占用的库位) - List locationList = iLocationService.list(new LambdaQueryWrapper().eq(Location::getLocationStatus, Location.STATUS_OCCUPIED)); + List locationList = iLocationService.list(new LambdaQueryWrapper().eq(Location::getLocationStatus, Location.STATUS_FREE)); if (!CollectionUtils.isEmpty(locationList)) { task.setLocationId(locationList.get(0).getId()); // 分配第一个可用库位 // 更新库位状态为空闲(锁定库位) Location location = locationList.get(0); - location.setLocationStatus(Location.STATUS_FREE); + location.setLocationStatus(Location.STATUS_OCCUPIED); iLocationService.updateById(location); return R.data(task); } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/StorageMonitoringServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/StorageMonitoringServiceImpl.java index 283fcacf..3b707009 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/StorageMonitoringServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/StorageMonitoringServiceImpl.java @@ -1,50 +1,185 @@ package org.springblade.desk.logistics.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.extern.slf4j.Slf4j; +import org.springblade.desk.logistics.pojo.entity.Location; +import org.springblade.desk.logistics.pojo.entity.Station; import org.springblade.desk.logistics.pojo.entity.Task; import org.springblade.desk.logistics.service.ILocationService; import org.springblade.desk.logistics.service.IStationService; import org.springblade.desk.logistics.service.IStorageMonitoringService; import org.springblade.desk.logistics.service.ITaskService; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; -import java.util.HashSet; -import java.util.Set; +import java.util.List; -@Service +/** + * 仓储监控服务实现类 + *

+ * 核心业务: + * 1. 定时(每5秒)扫描系统中所有空闲状态的站点 + * 2. 为每个空闲站点匹配最早创建的待库位任务 + * 3. 更新任务关联库位为空闲状态,并绑定站点与任务关系 + * 4. 触发AGV小车移动指令(待实现) + *

+ * 设计思路: + * - 采用定时任务自动巡检,减少人工干预 + * - 按任务创建时间升序匹配,保证任务执行的公平性 + * - 增加多层空值防护和状态校验,避免无效数据库操作 + * + * @author (可补充作者信息) + * @date 2026-03-05 + * @version 1.0 + */ +@Service // Spring业务层注解,将类注册为Spring Bean +@Slf4j // Lombok日志注解,自动生成log对象,无需手动创建Logger public class StorageMonitoringServiceImpl implements IStorageMonitoringService { - private static final Set RUNNING_STATUSES = new HashSet<>(); - - static { - // 初始化运行中任务状态 - RUNNING_STATUSES.add(Task.STATUS_START); // 任务启动 - RUNNING_STATUSES.add(Task.STATUS_CONVEYOR_START); // 输送机启动 - RUNNING_STATUSES.add(Task.STATUS_CONVEYOR_END); // 输送机结束 - RUNNING_STATUSES.add(Task.STATUS_STATION); // 站点状态 - RUNNING_STATUSES.add(Task.STATUS_LOCATION); // 库位状态 - RUNNING_STATUSES.add(Task.STATUS_WAITING); // 等待状态 - RUNNING_STATUSES.add(Task.STATUS_STATION_RECEIVE);// 站点接收 - RUNNING_STATUSES.add(Task.STATUS_BACK_TO_STORAGE);// 返库状态 - } + /** - * 任务服务:处理箱绑定任务的创建、状态更新、删除等 + * 任务业务服务:提供任务的CRUD、状态查询、条件筛选等操作 */ - private final ITaskService iTaskService; + private final ITaskService taskService; + /** - * 站点服务:处理站点状态(占用/空闲)管理 + * 站点业务服务:提供站点状态管理、站点信息查询等操作 */ - private final IStationService iStationService; + private final IStationService stationService; + /** - * 库位服务:处理库位状态(占用/空闲)管理 + * 库位业务服务:提供库位状态更新、库位信息查询等操作 */ - private final ILocationService iLocationService; - public StorageMonitoringServiceImpl(ITaskService iTaskService, IStationService iStationService, ILocationService iLocationService) { - this.iTaskService = iTaskService; - this.iStationService = iStationService; - this.iLocationService = iLocationService; + private final ILocationService locationService; + + /** + * 构造器注入依赖(Spring官方推荐方式) + *

+ * 优势: + * 1. 强制依赖注入,避免NPE(空指针异常) + * 2. 便于单元测试时模拟依赖 + * 3. 符合依赖倒置原则,降低耦合 + * + * @param taskService 任务服务Bean(Spring自动注入) + * @param stationService 站点服务Bean(Spring自动注入) + * @param locationService 库位服务Bean(Spring自动注入) + */ + public StorageMonitoringServiceImpl(ITaskService taskService, IStationService stationService, ILocationService locationService) { + this.taskService = taskService; + this.stationService = stationService; + this.locationService = locationService; } - @Override + /** + * 仓储空闲站点监控核心方法(定时执行) + *

+ * 执行频率:每5秒执行一次 + * 核心流程: + * 1. 拉取全量空闲状态的站点列表 + * 2. 遍历每个空闲站点,匹配对应工位的待库位任务 + * 3. 对首个任务关联的库位执行「置为空闲」操作 + * 4. 绑定任务与站点关系,更新站点预占用状态 + * 5. 触发AGV小车移动指令(待实现) + *

+ * 异常防护: + * - 空集合直接返回,避免循环空指针 + * - 库位ID/任务/库位信息空值校验,跳过异常数据 + * - 状态未变化时跳过更新,减少数据库IO + */ + @Scheduled(cron = "*/5 * * * * ?") // Spring定时任务注解,cron表达式控制执行频率 + @Override // 实现IStorageMonitoringService接口的抽象方法 public void monitoringStation() { + // ========== 步骤1:查询所有空闲状态的站点 ========== + List stationList = stationService.list( + new LambdaQueryWrapper() + .eq(Station::getStationStatus, Station.STATUS_FREE) // 筛选条件:站点状态为空闲 + ); + // 日志打印空闲站点数量,便于监控和问题排查 + log.info("【仓储监控】定时任务执行 - 查询到空闲站点数量:{}", stationList == null ? 0 : stationList.size()); + + // 空值防护:无空闲站点时直接返回,避免后续无效操作 + if (stationList == null || stationList.isEmpty()) { + log.warn("【仓储监控】定时任务执行 - 未查询到空闲站点,任务提前结束"); + return; + } + + // ========== 步骤2:遍历空闲站点处理关联任务 ========== + int processedCount = 0; // 统计成功处理的站点数量 + for (Station station : stationList) { + // 打印当前处理的站点信息,便于定位单站点异常 + log.info("【仓储监控】开始处理站点 - 站点ID:{},工位ID:{}", station.getId(), station.getWcId()); + + try { + // ========== 步骤2.1:查询对应工位的待库位任务(按创建时间升序) ========== + List taskList = taskService.list( + new LambdaQueryWrapper() + .eq(Task::getTaskStatus, Task.STATUS_LOCATION) // 任务状态:待库位 + .eq(Task::getWcId, station.getWcId()) // 匹配当前站点的工位ID + .orderByAsc(Task::getCreateTime) // 按创建时间升序,优先处理最早创建的任务 + ); + + // 无待处理任务时跳过当前站点 + if (taskList == null || taskList.isEmpty()) { + log.info("【仓储监控】站点ID:{} - 未查询到待库位任务,跳过处理", station.getId()); + continue; + } + + // ========== 步骤2.2:获取首个任务并校验关联库位ID ========== + Task firstTask = taskList.get(0); // 取最早创建的待库位任务 + Long locationId = firstTask.getLocationId(); // 获取任务关联的库位ID + log.info("【仓储监控】站点ID:{} - 匹配到首个待库位任务,任务ID:{},关联库位ID:{}", + station.getId(), firstTask.getId(), locationId); + + // 空值防护:库位ID为空时跳过,避免后续查询异常 + if (locationId == null) { + log.error("【仓储监控】任务ID:{} - 关联库位ID为空,跳过当前站点处理", firstTask.getId()); + continue; + } + + // ========== 步骤2.3:查询库位信息并更新状态为空闲 ========== + Location location = locationService.getById(locationId); // 根据库位ID查询库位信息 + // 库位不存在时跳过 + if (location == null) { + log.error("【仓储监控】库位ID:{} - 库位信息不存在,跳过当前站点处理", locationId); + continue; + } + + // 状态校验:库位已为空闲时跳过更新,减少数据库操作 + if (Location.STATUS_FREE.equals(location.getLocationStatus())) { + log.info("【仓储监控】库位ID:{} - 已为空闲状态,无需更新", locationId); + } else { + // 更新库位状态为空闲 + location.setLocationStatus(Location.STATUS_FREE); + boolean updateResult = locationService.updateById(location); + if (updateResult) { + log.info("【仓储监控】库位ID:{} - 状态更新为空闲成功", locationId); + } else { + log.error("【仓储监控】库位ID:{} - 状态更新为空闲失败,跳过后续操作", locationId); + continue; // 更新失败时不触发AGV指令 + } + } + + // ========== 步骤2.4:绑定任务与站点关系,更新站点预占用状态 ========== + firstTask.setStationId(station.getId()); // 任务绑定当前站点ID + taskService.updateById(firstTask); // 保存任务关联关系 + station.setStationStatus(Station.PRE_STATUS_OCCUPIED); // 站点置为预占用状态 + stationService.updateById(station); // 保存站点状态 + + // ========== 步骤2.5:触发AGV小车移动指令(待实现) ========== + log.info("【仓储监控】站点ID:{} - 准备调用AGV接口,任务ID:{},库位ID:{}", + station.getId(), firstTask.getId(), locationId); + // todo: 调用AGV接口传递任务ID和站点ID,触发小车移动 + // agvService.dispatchAgv(firstTask.getId(), station.getId()); + + processedCount++; // 成功处理计数+1 + + } catch (Exception e) { + // 单个站点处理异常不影响其他站点,记录异常日志便于排查 + log.error("【仓储监控】站点ID:{} - 处理过程中发生异常,跳过当前站点", station.getId(), e); + continue; + } + } + // ========== 任务结束:打印处理结果 ========== + log.info("【仓储监控】定时任务执行完成 - 总计扫描空闲站点:{},成功处理:{}", stationList.size(), processedCount); } -} +} \ No newline at end of file diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskExecuteRecordServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskExecuteRecordServiceImpl.java index 52114fcf..b4af4d54 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskExecuteRecordServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskExecuteRecordServiceImpl.java @@ -1,47 +1,26 @@ -/** - * BladeX Commercial License Agreement - * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved. - *

- * Use of this software is governed by the Commercial License Agreement - * obtained after purchasing a license from BladeX. - *

- * 1. This software is for development use only under a valid license - * from BladeX. - *

- * 2. Redistribution of this software's source code to any third party - * without a commercial license is strictly prohibited. - *

- * 3. Licensees may copyright their own code but cannot use segments - * from this software for such purposes. Copyright of this software - * remains with BladeX. - *

- * Using this software signifies agreement to this License, and the software - * must not be used for illegal purposes. - *

- * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is - * not liable for any claims arising from secondary or illegal development. - *

- * Author: Chill Zhuang (bladejava@qq.com) - */ + package org.springblade.desk.logistics.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.extern.slf4j.Slf4j; import org.springblade.core.mp.base.BaseServiceImpl; import org.springblade.core.tool.api.R; -import org.springblade.desk.logistics.mapper.OrderBindMapper; import org.springblade.desk.logistics.mapper.TaskExecuteRecordMapper; -import org.springblade.desk.logistics.pojo.entity.AGVCallBack; -import org.springblade.desk.logistics.pojo.entity.OrderBind; + +import org.springblade.desk.logistics.pojo.dto.AGVCallBackDto; import org.springblade.desk.logistics.pojo.entity.TaskExecuteRecord; -import org.springblade.desk.logistics.service.IOrderBindService; import org.springblade.desk.logistics.service.ITaskExecuteRecordService; import org.springframework.stereotype.Service; import java.util.List; /** - * 物流小车对接实体类 服务实现类 + * 物流AGV小车任务执行记录服务实现类 + *

+ * 核心功能: + * 1. 处理AGV小车执行任务后的回调通知 + * 2. 更新任务执行记录的状态、起始/结束位置等关键信息 + * 3. 任务完成时触发后续的业务接口调用(东哥接口) * * @author BladeX * @since 2025-11-12 @@ -50,23 +29,83 @@ import java.util.List; @Slf4j public class TaskExecuteRecordServiceImpl extends BaseServiceImpl implements ITaskExecuteRecordService { - + /** + * AGV小车任务状态回调接口 + *

+ * 处理逻辑: + * 1. 接收AGV小车的回调参数,记录日志并校验任务单号是否存在 + * 2. 清理回调方法名的空格,更新任务执行记录的方法字段 + * 3. 根据不同的任务状态(启动/出仓/结束)更新对应的位置信息 + * 4. 保存更新后的任务记录,失败则返回错误结果 + * 5. 任务结束时触发东哥接口调用(待实现) + * + * @param agvCallBack AGV小车回调参数实体,包含任务单号、执行方法、当前位置等信息 + * @return R 统一返回结果: + * - 成功:R.success() + * - 失败:R.fail(错误信息) + */ @Override - public R agvCallback(AGVCallBack agvCallBack) { - log.info("agv小车接口调用参数入参:{}",agvCallBack); - List list = list(new LambdaQueryWrapper().eq(TaskExecuteRecord::getId, agvCallBack.getTaskCode()).orderByDesc(TaskExecuteRecord::getCreateTime)); - if (list==null||list.size()==0) { + public R agvCallback(AGVCallBackDto agvCallBack) { + // 记录AGV回调入参,便于问题排查 + log.info("agv小车接口调用参数入参:{}", agvCallBack); + + // 1. 根据任务单号查询最新的任务执行记录(按创建时间降序,取第一条) + List list = list( + new LambdaQueryWrapper() + .eq(TaskExecuteRecord::getId, agvCallBack.getTaskCode()) + .orderByDesc(TaskExecuteRecord::getCreateTime) + ); + + // 校验:未查询到任务记录,返回失败 + if (list == null || list.isEmpty()) { + log.warn("AGV回调失败:未查询到任务单号为{}的执行记录", agvCallBack.getTaskCode()); return R.fail("未查询到该任务单号"); } + + // 取最新的任务执行记录 TaskExecuteRecord taskExecuteRecord = list.get(0); + + // 2. 清理方法名中的空格(避免因空格导致状态判断错误) String method = agvCallBack.getMethod().replaceAll(" ", ""); taskExecuteRecord.setMethod(method); - if (!updateById(taskExecuteRecord)) { + + // 3. 根据不同的任务状态更新对应的位置信息 + switch (method) { + // 任务启动/出仓状态:更新起始位置 + case TaskExecuteRecord.STATUS_START: + case TaskExecuteRecord.STATUS_OUTBIN: + taskExecuteRecord.setStartPos(agvCallBack.getCurrentPositionCode()); + log.info("任务单号{}:更新起始位置为{},状态为{}", + agvCallBack.getTaskCode(), agvCallBack.getCurrentPositionCode(), method); + break; + // 任务结束状态:更新结束位置 + case TaskExecuteRecord.STATUS_END: + taskExecuteRecord.setEndPos(agvCallBack.getCurrentPositionCode()); + log.info("任务单号{}:更新结束位置为{},状态为{}", + agvCallBack.getTaskCode(), agvCallBack.getCurrentPositionCode(), method); + break; + // 其他状态:暂不处理位置信息 + default: + log.info("任务单号{}:状态{}无需更新位置信息", agvCallBack.getTaskCode(), method); + break; + } + + // 4. 保存更新后的任务记录 + boolean updateResult = updateById(taskExecuteRecord); + if (!updateResult) { + log.error("AGV回调失败:任务单号{}的执行记录更新保存失败", agvCallBack.getTaskCode()); return R.fail("保存该任务单号失败"); } + + // 5. 任务结束状态:触发后续的东哥接口调用(待实现) if (method.equals(TaskExecuteRecord.STATUS_END)) { + log.info("任务单号{}已完成,准备调用东哥接口", agvCallBack.getTaskCode()); //todo: 调用东哥接口 + // eastBrotherService.notifyTaskComplete(agvCallBack.getTaskCode()); } + + // 回调处理成功 + log.info("AGV回调成功:任务单号{}的执行记录已更新,状态为{}", agvCallBack.getTaskCode(), method); return R.success(); } -} +} \ No newline at end of file diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskServiceImpl.java index 0f3484e1..4b470cd4 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/logistics/service/impl/TaskServiceImpl.java @@ -25,16 +25,20 @@ */ package org.springblade.desk.logistics.service.impl; +import com.baomidou.mybatisplus.core.metadata.IPage; import lombok.extern.slf4j.Slf4j; import org.checkerframework.checker.units.qual.A; import org.springblade.core.mp.base.BaseServiceImpl; import org.springblade.desk.logistics.mapper.TaskMapper; +import org.springblade.desk.logistics.pojo.dto.TaskDto; import org.springblade.desk.logistics.pojo.entity.Task; +import org.springblade.desk.logistics.pojo.vo.TaskVO; import org.springblade.desk.logistics.service.ITaskService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.math.BigDecimal; +import java.util.List; /** * 物流任务 服务类 @@ -63,4 +67,10 @@ public class TaskServiceImpl extends BaseServiceImpl implement public Task getBoxBarcode(String boxBarcode) { return taskMapper.selectByBoxBarcode(boxBarcode); } + + @Override + public IPage selectPage(IPage page, TaskDto taskDto) { + List taskVOList = taskMapper.selectEquipmentPage(page, taskDto); + return page.setRecords(taskVOList); + } }