diff --git a/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/basedata_manage/service/dao/Structattr.java b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/basedata_manage/service/dao/Structattr.java
index 7b6800b..79ba26b 100644
--- a/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/basedata_manage/service/dao/Structattr.java
+++ b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/basedata_manage/service/dao/Structattr.java
@@ -1,5 +1,6 @@
package org.nl.wms.basedata_manage.service.dao;
+import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@@ -305,4 +306,10 @@ public class Structattr implements Serializable {
*/
private String remark;
+ /**
+ * 备注任务标识
+ */
+ @TableField(exist = false)
+ private String task_id;
+
}
diff --git a/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch_manage/service/util/tasks/EmpOutMoveTask.java b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch_manage/service/util/tasks/EmpOutMoveTask.java
new file mode 100644
index 0000000..7e56bb6
--- /dev/null
+++ b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch_manage/service/util/tasks/EmpOutMoveTask.java
@@ -0,0 +1,221 @@
+package org.nl.wms.sch_manage.service.util.tasks;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import org.nl.common.exception.BadRequestException;
+import org.nl.common.utils.CodeUtil;
+import org.nl.common.utils.SecurityUtils;
+import org.nl.config.IdUtil;
+import org.nl.wms.basedata_manage.service.IStructattrService;
+import org.nl.wms.basedata_manage.service.dao.Structattr;
+import org.nl.wms.sch_manage.enums.TaskStatus;
+import org.nl.wms.sch_manage.service.ISchBaseTaskService;
+import org.nl.wms.sch_manage.service.dao.SchBaseTask;
+import org.nl.wms.sch_manage.service.util.ACSTaskTypeEnum;
+import org.nl.wms.sch_manage.service.util.AbstractTask;
+import org.nl.wms.sch_manage.service.util.AcsTaskDto;
+import org.nl.wms.sch_manage.service.util.TaskType;
+import org.nl.wms.warehouse_management.enums.IOSConstant;
+import org.nl.wms.warehouse_management.enums.IOSEnum;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ *
+ * 空载具出库移库任务类
+ *
+ *
+ * @author Liuxy
+ * @since 2025-09-12
+ */
+@Component(value = "EmpOutMoveTask")
+@TaskType("EmpOutMoveTask")
+public class EmpOutMoveTask extends AbstractTask {
+
+ /**
+ * 任务服务类
+ */
+ @Autowired
+ private ISchBaseTaskService taskService;
+
+ /**
+ * 仓位服务
+ */
+ @Autowired
+ private IStructattrService iStructattrService;
+
+ @Override
+ public String create(JSONObject json) {
+ SchBaseTask task = new SchBaseTask();
+ task.setTask_id(IdUtil.getStringId());
+ task.setTask_code(CodeUtil.getNewCode("TASK_CODE"));
+ task.setTask_status(TaskStatus.CREATE.getCode());
+ task.setConfig_code(EmpOutMoveTask.class.getSimpleName());
+ task.setPoint_code1(json.getString("point_code1"));
+ task.setPoint_code2(json.getString("point_code2"));
+ task.setVehicle_code(json.getString("vehicle_code"));
+ task.setVehicle_code2(json.getString("vehicle_code2"));
+ task.setGroup_id(json.getString("group_id"));
+ task.setRequest_param(json.toString());
+ task.setPriority(json.getString("Priority"));
+ task.setIs_wait(json.getString("is_wait"));
+ task.setCreate_id(SecurityUtils.getCurrentUserId());
+ task.setCreate_name(SecurityUtils.getCurrentNickName());
+ task.setCreate_time(DateUtil.now());
+ taskService.save(task);
+
+ // 下发任务
+ this.sendTaskOne(task.getTask_id());
+ return task.getTask_id();
+ }
+
+ @Override
+ public AcsTaskDto sendAcsParam(String taskId) {
+ SchBaseTask taskDao = taskService.getById(taskId);
+
+ // 组织下发给acs的数据
+ AcsTaskDto acsTaskDto = new AcsTaskDto();
+ acsTaskDto.setExt_task_id(taskDao.getTask_id());
+ acsTaskDto.setTask_code(taskDao.getTask_code());
+ acsTaskDto.setStart_device_code(taskDao.getPoint_code1());
+ acsTaskDto.setNext_device_code(taskDao.getPoint_code2());
+ acsTaskDto.setVehicle_code(taskDao.getVehicle_code());
+
+ acsTaskDto.setVehicle_type(IOSConstant.ONE);
+ acsTaskDto.setIs_wait(IOSConstant.ZERO);
+ acsTaskDto.setTask_type(ACSTaskTypeEnum.CTU_TASK.getCode());
+
+ acsTaskDto.setPriority(IOSConstant.ONE);
+ acsTaskDto.setAgv_system_type(IOSConstant.THREE);
+ acsTaskDto.setIs_get_pause(IOSConstant.ZERO);
+ acsTaskDto.setIs_put_pause(IOSConstant.ZERO);
+
+ return acsTaskDto;
+ }
+
+ @Override
+ @Transactional
+ protected void updateStatus(String task_code, TaskStatus status) {
+ // 校验任务
+ SchBaseTask taskObj = taskService.getByCode(task_code);
+ if (taskObj.getTask_status().equals(TaskStatus.FINISHED.getCode())) {
+ throw new BadRequestException("该任务已完成!");
+ }
+ if (taskObj.getTask_status().equals(TaskStatus.CANCELED.getCode())) {
+ throw new BadRequestException("该任务已取消!");
+ }
+ // 根据传来的类型去对任务进行操作
+ if (status.equals(TaskStatus.EXECUTING)) {
+ taskObj.setTask_status(TaskStatus.EXECUTING.getCode());
+ taskObj.setRemark("执行中");
+ taskService.updateById(taskObj);
+ }
+ if (status.equals(TaskStatus.FINISHED)) {
+ this.finishTask(taskObj);
+ }
+ if (status.equals(TaskStatus.CANCELED)) {
+ this.cancelTask(taskObj);
+ }
+ }
+
+ @Override
+ @Transactional
+ public void forceFinish(String task_code) {
+ SchBaseTask taskObj = taskService.getByCode(task_code);
+ if (ObjectUtil.isEmpty(taskObj)) {
+ throw new BadRequestException("该任务不存在");
+ }
+ this.finishTask(taskObj);
+ }
+
+ @Override
+ @Transactional
+ public void cancel(String task_code) {
+ SchBaseTask taskObj = taskService.getByCode(task_code);
+ if (ObjectUtil.isEmpty(taskObj)) {
+ throw new BadRequestException("该任务不存在");
+ }
+ if (Integer.parseInt(taskObj.getTask_status()) > Integer.parseInt(TaskStatus.CREATE.getCode())) {
+ throw new BadRequestException("只能取消生成中的任务!");
+ }
+ this.cancelTask(taskObj);
+ }
+
+ @Override
+ public void taskConfirm(String task_code) {
+ }
+
+ @Override
+ public JSONObject resultWeigh(SchBaseTask taskObj) {
+ return null;
+ }
+
+ @Transactional
+ public void finishTask(SchBaseTask taskObj) {
+ // 起点货位
+ Structattr startStruct = iStructattrService.getByCode(taskObj.getPoint_code1());
+ // 终点货位
+ Structattr endStruct = iStructattrService.getByCode(taskObj.getPoint_code2());
+
+ // 更新起点
+ iStructattrService.update(
+ new UpdateWrapper().lambda()
+ .eq(Structattr::getStruct_code, taskObj.getPoint_code1())
+ .set(Structattr::getLock_type, IOSEnum.LOCK_TYPE.code("空托盘出库锁"))
+ .set(Structattr::getStoragevehicle_code, endStruct.getStoragevehicle_code())
+ .set(Structattr::getIs_emptyvehicle,
+ endStruct.getIs_emptyvehicle().equals(IOSConstant.IS_DELETE_YES) ? IOSConstant.IS_DELETE_YES
+ : IOSConstant.IS_DELETE_NO
+ )
+ );
+
+ // 更新终点
+ iStructattrService.update(
+ new UpdateWrapper().lambda()
+ .eq(Structattr::getStruct_code, taskObj.getPoint_code2())
+ .set(Structattr::getLock_type, IOSEnum.LOCK_TYPE.code("未锁定"))
+ .set(Structattr::getStoragevehicle_code, startStruct.getStoragevehicle_code())
+ .set(Structattr::getIs_emptyvehicle,
+ startStruct.getIs_emptyvehicle().equals(IOSConstant.IS_DELETE_YES) ? IOSConstant.IS_DELETE_YES
+ : IOSConstant.IS_DELETE_NO
+ )
+ );
+
+ // 更新任务状态
+ taskObj.setRemark("已完成");
+ taskObj.setTask_status(TaskStatus.FINISHED.getCode());
+ taskService.updateById(taskObj);
+ }
+
+ @Transactional
+ public void cancelTask(SchBaseTask taskObj) {
+
+ // 取消空载具出库任务
+ SchBaseTask empTask = taskService.getById(taskObj.getExt_group_data());
+ empTask.setRemark("已取消");
+ empTask.setTask_status(TaskStatus.CANCELED.getCode());
+ taskService.updateById(empTask);
+
+
+ // 更新起点
+ iStructattrService.update(
+ new UpdateWrapper().lambda()
+ .eq(Structattr::getStruct_code, taskObj.getPoint_code1())
+ .set(Structattr::getLock_type, IOSEnum.LOCK_TYPE.code("未锁定"))
+ );
+ // 更新终点
+ iStructattrService.update(
+ new UpdateWrapper().lambda()
+ .eq(Structattr::getStruct_code, taskObj.getPoint_code2())
+ .set(Structattr::getLock_type, IOSEnum.LOCK_TYPE.code("未锁定"))
+ );
+
+ // 更新当前任务状态
+ taskObj.setRemark("已取消");
+ taskObj.setTask_status(TaskStatus.CANCELED.getCode());
+ taskService.updateById(taskObj);
+ }
+}
diff --git a/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch_manage/service/util/tasks/IosOutMoveTask.java b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch_manage/service/util/tasks/IosOutMoveTask.java
new file mode 100644
index 0000000..311c025
--- /dev/null
+++ b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/sch_manage/service/util/tasks/IosOutMoveTask.java
@@ -0,0 +1,250 @@
+package org.nl.wms.sch_manage.service.util.tasks;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import org.nl.common.exception.BadRequestException;
+import org.nl.common.utils.CodeUtil;
+import org.nl.common.utils.SecurityUtils;
+import org.nl.config.IdUtil;
+import org.nl.wms.basedata_manage.service.IStructattrService;
+import org.nl.wms.basedata_manage.service.dao.Structattr;
+import org.nl.wms.sch_manage.enums.TaskStatus;
+import org.nl.wms.sch_manage.service.ISchBaseTaskService;
+import org.nl.wms.sch_manage.service.dao.SchBaseTask;
+import org.nl.wms.sch_manage.service.util.ACSTaskTypeEnum;
+import org.nl.wms.sch_manage.service.util.AbstractTask;
+import org.nl.wms.sch_manage.service.util.AcsTaskDto;
+import org.nl.wms.sch_manage.service.util.TaskType;
+import org.nl.wms.warehouse_management.enums.IOSConstant;
+import org.nl.wms.warehouse_management.enums.IOSEnum;
+import org.nl.wms.warehouse_management.service.dao.IOStorInvDis;
+import org.nl.wms.warehouse_management.service.dao.mapper.IOStorInvDisMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+
+/**
+ *
+ * 出库单出库移库任务类
+ *
+ *
+ * @author Liuxy
+ * @since 2025-09-12
+ */
+@Component(value = "IosOutMoveTask")
+@TaskType("IosOutMoveTask")
+public class IosOutMoveTask extends AbstractTask {
+
+ /**
+ * 任务服务类
+ */
+ @Autowired
+ private ISchBaseTaskService taskService;
+
+ /**
+ * 仓位服务
+ */
+ @Autowired
+ private IStructattrService iStructattrService;
+
+ /*
+ * 分配明细mapper
+ */
+ @Resource
+ private IOStorInvDisMapper ioStorInvDisMapper;
+
+ @Override
+ public String create(JSONObject json) {
+ SchBaseTask task = new SchBaseTask();
+ task.setTask_id(IdUtil.getStringId());
+ task.setTask_code(CodeUtil.getNewCode("TASK_CODE"));
+ task.setTask_status(TaskStatus.CREATE.getCode());
+ task.setConfig_code(IosOutMoveTask.class.getSimpleName());
+ task.setPoint_code1(json.getString("point_code1"));
+ task.setPoint_code2(json.getString("point_code2"));
+ task.setVehicle_code(json.getString("vehicle_code"));
+ task.setVehicle_code2(json.getString("vehicle_code2"));
+ task.setExt_group_data(json.getString("ext_group_data"));
+ task.setGroup_id(json.getString("group_id"));
+ task.setRequest_param(json.toString());
+ task.setPriority(json.getString("Priority"));
+ task.setIs_wait(json.getString("is_wait"));
+ task.setCreate_id(SecurityUtils.getCurrentUserId());
+ task.setCreate_name(SecurityUtils.getCurrentNickName());
+ task.setCreate_time(DateUtil.now());
+ taskService.save(task);
+
+ // 下发任务
+ this.sendTaskOne(task.getTask_id());
+ return task.getTask_id();
+ }
+
+ @Override
+ public AcsTaskDto sendAcsParam(String taskId) {
+ SchBaseTask taskDao = taskService.getById(taskId);
+
+ // 组织下发给acs的数据
+ AcsTaskDto acsTaskDto = new AcsTaskDto();
+ acsTaskDto.setExt_task_id(taskDao.getTask_id());
+ acsTaskDto.setTask_code(taskDao.getTask_code());
+ acsTaskDto.setStart_device_code(taskDao.getPoint_code1());
+ acsTaskDto.setNext_device_code(taskDao.getPoint_code2());
+ acsTaskDto.setVehicle_code(taskDao.getVehicle_code());
+
+ acsTaskDto.setVehicle_type(IOSConstant.ONE);
+ acsTaskDto.setIs_wait(IOSConstant.ZERO);
+ acsTaskDto.setTask_type(ACSTaskTypeEnum.CTU_TASK.getCode());
+
+ acsTaskDto.setPriority(IOSConstant.ONE);
+ acsTaskDto.setAgv_system_type(IOSConstant.THREE);
+ acsTaskDto.setIs_get_pause(IOSConstant.ZERO);
+ acsTaskDto.setIs_put_pause(IOSConstant.ZERO);
+
+ return acsTaskDto;
+ }
+
+ @Override
+ @Transactional
+ protected void updateStatus(String task_code, TaskStatus status) {
+ // 校验任务
+ SchBaseTask taskObj = taskService.getByCode(task_code);
+ if (taskObj.getTask_status().equals(TaskStatus.FINISHED.getCode())) {
+ throw new BadRequestException("该任务已完成!");
+ }
+ if (taskObj.getTask_status().equals(TaskStatus.CANCELED.getCode())) {
+ throw new BadRequestException("该任务已取消!");
+ }
+ // 根据传来的类型去对任务进行操作
+ if (status.equals(TaskStatus.EXECUTING)) {
+ taskObj.setTask_status(TaskStatus.EXECUTING.getCode());
+ taskObj.setRemark("执行中");
+ taskService.updateById(taskObj);
+ }
+ if (status.equals(TaskStatus.FINISHED)) {
+ this.finishTask(taskObj);
+ }
+ if (status.equals(TaskStatus.CANCELED)) {
+ this.cancelTask(taskObj);
+ }
+ }
+
+ @Override
+ @Transactional
+ public void forceFinish(String task_code) {
+ SchBaseTask taskObj = taskService.getByCode(task_code);
+ if (ObjectUtil.isEmpty(taskObj)) {
+ throw new BadRequestException("该任务不存在");
+ }
+ this.finishTask(taskObj);
+ }
+
+ @Override
+ @Transactional
+ public void cancel(String task_code) {
+ SchBaseTask taskObj = taskService.getByCode(task_code);
+ if (ObjectUtil.isEmpty(taskObj)) {
+ throw new BadRequestException("该任务不存在");
+ }
+ if (Integer.parseInt(taskObj.getTask_status()) > Integer.parseInt(TaskStatus.CREATE.getCode())) {
+ throw new BadRequestException("只能取消生成中的任务!");
+ }
+ this.cancelTask(taskObj);
+ }
+
+ @Override
+ public void taskConfirm(String task_code) {
+ }
+
+ @Override
+ public JSONObject resultWeigh(SchBaseTask taskObj) {
+ return null;
+ }
+
+ @Transactional
+ public void finishTask(SchBaseTask taskObj) {
+ // 起点货位
+ Structattr startStruct = iStructattrService.getByCode(taskObj.getPoint_code1());
+ // 终点货位
+ Structattr endStruct = iStructattrService.getByCode(taskObj.getPoint_code2());
+
+ // 更新起点
+ iStructattrService.update(
+ new UpdateWrapper().lambda()
+ .eq(Structattr::getStruct_code, taskObj.getPoint_code1())
+ .set(Structattr::getLock_type, IOSEnum.LOCK_TYPE.code("出库锁"))
+ .set(Structattr::getStoragevehicle_code, endStruct.getStoragevehicle_code())
+ .set(Structattr::getInv_id, endStruct.getInv_id())
+ .set(Structattr::getInv_code, endStruct.getInv_code())
+ .set(Structattr::getInv_type, endStruct.getInv_type())
+ .set(Structattr::getIs_emptyvehicle,
+ endStruct.getIs_emptyvehicle().equals(IOSConstant.IS_DELETE_YES) ? IOSConstant.IS_DELETE_YES
+ : IOSConstant.IS_DELETE_NO
+ )
+ );
+
+ // 更新终点
+ iStructattrService.update(
+ new UpdateWrapper().lambda()
+ .eq(Structattr::getStruct_code, taskObj.getPoint_code2())
+ .set(Structattr::getLock_type, IOSEnum.LOCK_TYPE.code("未锁定"))
+ .set(Structattr::getStoragevehicle_code, startStruct.getStoragevehicle_code())
+ .set(Structattr::getInv_id, null)
+ .set(Structattr::getInv_code, null)
+ .set(Structattr::getInv_type, null)
+ .set(Structattr::getIs_emptyvehicle,
+ startStruct.getIs_emptyvehicle().equals(IOSConstant.IS_DELETE_YES) ? IOSConstant.IS_DELETE_YES
+ : IOSConstant.IS_DELETE_NO
+ )
+ );
+
+ // 更新任务状态
+ taskObj.setRemark("已完成");
+ taskObj.setTask_status(TaskStatus.FINISHED.getCode());
+ taskService.updateById(taskObj);
+ }
+
+ @Transactional
+ public void cancelTask(SchBaseTask taskObj) {
+ // 查询终点仓位信息
+ Structattr attrDao = iStructattrService.getByCode(taskObj.getPoint_code2());
+
+ // 还原出库分配明细仓位 / 取消分配明细任务
+ IOStorInvDis ioStorInvDis = ioStorInvDisMapper.selectById(taskObj.getExt_group_data());
+ // 取消分配明细任务
+ SchBaseTask disTask = taskService.getById(ioStorInvDis.getTask_id());
+ disTask.setRemark("已取消");
+ disTask.setTask_status(TaskStatus.CANCELED.getCode());
+ taskService.updateById(disTask);
+
+ ioStorInvDis.setStruct_id(attrDao.getStruct_id());
+ ioStorInvDis.setStruct_code(attrDao.getStruct_code());
+ ioStorInvDis.setStruct_name(attrDao.getStruct_name());
+ ioStorInvDis.setTask_id("");
+ ioStorInvDis.setPoint_code("");
+ ioStorInvDis.setIs_issued(IOSConstant.ZERO);
+ ioStorInvDis.setWork_status(IOSEnum.INBILL_DIS_STATUS.code("未生成"));
+ ioStorInvDisMapper.updateById(ioStorInvDis);
+
+ // 更新起点
+ iStructattrService.update(
+ new UpdateWrapper().lambda()
+ .eq(Structattr::getStruct_code, taskObj.getPoint_code1())
+ .set(Structattr::getLock_type, IOSEnum.LOCK_TYPE.code("未锁定"))
+ );
+ // 更新终点
+ iStructattrService.update(
+ new UpdateWrapper().lambda()
+ .eq(Structattr::getStruct_code, taskObj.getPoint_code2())
+ .set(Structattr::getLock_type, IOSEnum.LOCK_TYPE.code("出库锁"))
+ );
+
+ // 更新任务状态
+ taskObj.setRemark("已取消");
+ taskObj.setTask_status(TaskStatus.CANCELED.getCode());
+ taskService.updateById(taskObj);
+ }
+}
diff --git a/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/warehouse_management/enums/IOSEnum.java b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/warehouse_management/enums/IOSEnum.java
index 6e2a75d..a9ee989 100644
--- a/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/warehouse_management/enums/IOSEnum.java
+++ b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/warehouse_management/enums/IOSEnum.java
@@ -73,6 +73,9 @@ public enum IOSEnum {
"库存锁","7", "回库锁","8", "其他锁","99"
)),
+ // 仓位类型
+ PLACEMENT_TYPE(MapOf.of("深货位", "1", "浅货位", "2")),
+
// 库区编码
SECT_CODE(MapOf.of("合格区", "HG01", "待检区", "DJ01", "不合格区", "BHG01")),
diff --git a/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/warehouse_management/service/IOutBillService.java b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/warehouse_management/service/IOutBillService.java
index a026811..f629932 100644
--- a/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/warehouse_management/service/IOutBillService.java
+++ b/wms/nladmin-system/nlsso-server/src/main/java/org/nl/wms/warehouse_management/service/IOutBillService.java
@@ -8,6 +8,7 @@ import org.nl.common.domain.query.PageQuery;
import org.nl.wms.basedata_manage.service.dto.MdPbStoragevehicleextDto;
import org.nl.wms.sch_manage.service.dao.SchBaseTask;
import org.nl.wms.warehouse_management.service.dao.IOStorInv;
+import org.nl.wms.warehouse_management.service.dao.IOStorInvDis;
import org.nl.wms.warehouse_management.service.dto.IOStorInvDisDto;
import org.nl.wms.warehouse_management.service.dto.IOStorInvDtlDto;
import org.springframework.data.domain.Pageable;
@@ -176,4 +177,19 @@ public interface IOutBillService extends IService {
* @return
*/
List