diff --git a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/EmptyRollerPointTypeEnum.java b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/EmptyRollerPointTypeEnum.java
new file mode 100644
index 00000000..47630234
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/EmptyRollerPointTypeEnum.java
@@ -0,0 +1,26 @@
+package cn.code.nl.module.lms.enums;
+
+import lombok.Getter;
+
+/**
+ * @author dsh
+ * 2026/7/28
+ */
+@Getter
+public enum EmptyRollerPointTypeEnum {
+
+ RAW_FOIL_EMPTY_ROLLER_POINT("1","生箔空辊点"),
+ CUT_EMPTY_ROLLER_POINT("2","分切空辊点"),
+ RAW_FOIL_EMPTY_ROLLER_WAIT_POINT("3","生箔空辊等待点"),
+ CUT_EMPTY_ROLLER_POINT_WAIT_POINT("4","分切空辊等待点");
+
+
+ private String code;
+
+ private String name;
+
+ EmptyRollerPointTypeEnum(String code,String name){
+ this.code = code;
+ this.name = name;
+ }
+}
diff --git a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/ErrorCodeConstants.java b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/ErrorCodeConstants.java
index bde6ac22..79b11d7b 100644
--- a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/ErrorCodeConstants.java
+++ b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/ErrorCodeConstants.java
@@ -17,4 +17,27 @@ public interface ErrorCodeConstants {
ErrorCode RAW_FOIL_WORK_ORDER_POINT_CODE_NOT_EXISTS = new ErrorCode(4, "点位设备不存在");
ErrorCode RAW_FOIL_WORK_ORDER_MATERIAL_NOT_EXISTS = new ErrorCode(5, "物料不存在");
ErrorCode RAW_FOIL_WORK_ORDER_ALREADY_ENDED = new ErrorCode(6, "不能对完成状态的工单强制结束");
+ ErrorCode RAW_FOIL_WORK_ORDER_STATUS_NOT_START = new ErrorCode(7, "工单状态不为开始");
+ ErrorCode RAW_FOIL_WORK_ORDER_POINT_CODE_NOT_USED = new ErrorCode(8, "生箔设备未启用");
+ ErrorCode RAW_FOIL_WORK_ORDER_POINT_OCCUPIED = new ErrorCode(12, "点位:{}被占用");
+ ErrorCode RAW_FOIL_WORK_ORDER_FAIL = new ErrorCode(15, "获取生箔工单存在未完成的任务异常");
+ ErrorCode RAW_FOIL_WORK_ORDER_NOT_SELECT = new ErrorCode(16, "生箔工单存在未完成的任务,请先完成任务");
+
+ // ========== 空辊缓存位 ==========
+ ErrorCode RAW_FOIL_EMPTY_ROLLER_CASHE_POSITION_NOT_EXISTS = new ErrorCode(9, "空辊缓存位不存在");
+ ErrorCode EMPTY_ROLLER_CASHE_POSITION_WAIT_POINT_NOT_EXISTS = new ErrorCode(10, "空辊缓存位找不到等待点");
+ ErrorCode EMPTY_ROLLER_CASHE_POSITION_NOT_ALLOCATE = new ErrorCode(18, "未查询到有空辊缓存位");
+
+ // ========== 生箔母卷缓存位 ==========
+ ErrorCode RAW_FOIL_CASHE_POSITION_NOT_EXISTS = new ErrorCode(11, "生箔母卷缓存位不存在");
+ ErrorCode RAW_FOIL_CASHE_POSITION_NOT_SELECT = new ErrorCode(13, "未查询到有生箔母卷缓存位");
+ ErrorCode RAW_FOIL_TRANSPORT_TASK_CREATE_FAIL = new ErrorCode(14, "创建搬运任务失败");
+
+ // =========== 生箔任务 ==========
+ ErrorCode RAW_FOIL_TASK_ERROR = new ErrorCode(17, "任务不存在或查询失败");
+
+ // ========== 生箔称重完成入库 ==========
+ ErrorCode RAW_FOIL_WORK_ORDER_STATUS_NOT_EXECUTION = new ErrorCode(19, "生箔工序工单状态不为执行中");
+ ErrorCode RAW_FOIL_WEIGHING_POSITION_NOT_EXISTS = new ErrorCode(20, "称重位不存在");
+ ErrorCode RAW_FOIL_CONTAINER_NOT_ON_WEIGHING_POSITION = new ErrorCode(21, "母卷不在称重位");
}
diff --git a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/LockStatusEnum.java b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/LockStatusEnum.java
new file mode 100644
index 00000000..8d09a040
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/LockStatusEnum.java
@@ -0,0 +1,24 @@
+package cn.code.nl.module.lms.enums;
+
+import lombok.Getter;
+
+/**
+ * @author dsh
+ * 2026/7/30
+ */
+@Getter
+public enum LockStatusEnum {
+
+ IDLE("0","空闲"),
+ OCCUPIED("1","占用");
+
+
+ private String code;
+
+ private String name;
+
+ LockStatusEnum(String code,String name){
+ this.code = code;
+ this.name = name;
+ }
+}
diff --git a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/RawFoilCashePositionTypeEnum.java b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/RawFoilCashePositionTypeEnum.java
new file mode 100644
index 00000000..501326c2
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/RawFoilCashePositionTypeEnum.java
@@ -0,0 +1,27 @@
+package cn.code.nl.module.lms.enums;
+
+import lombok.Getter;
+
+/**
+ * @author dsh
+ * 2026/7/28
+ */
+@Getter
+public enum RawFoilCashePositionTypeEnum {
+
+ CONVENTIONAL("1","常规"),
+ WEIGHING_BUFFER_POSITION("2","称重缓存位"),
+ WEIGHING_POSITION("3","称重位");
+
+
+ private String code;
+
+ private String name;
+
+ RawFoilCashePositionTypeEnum(String code,String name){
+ this.code = code;
+ this.name = name;
+ }
+
+
+}
diff --git a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/RawFoilHandleCodeConstants.java b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/RawFoilHandleCodeConstants.java
new file mode 100644
index 00000000..44cd7035
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/RawFoilHandleCodeConstants.java
@@ -0,0 +1,14 @@
+package cn.code.nl.module.lms.enums;
+
+/**
+ * 生箔工序任务回调处理器编码常量
+ * @author dsh
+ * 2026/7/28
+ */
+public interface RawFoilHandleCodeConstants {
+
+ String RAW_FOIL_TASK = "rawFoilTask";
+
+ /** 生箔入库任务(称重完成 → 常规缓存位)回调处理器编码 */
+ String RAW_FOIL_INSTORAGE_TASK = "rawFoilInstorageTask";
+}
diff --git a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/RawFoilWorkOrderStatusEnum.java b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/RawFoilWorkOrderStatusEnum.java
index 6e64e4b2..c3cbcb12 100644
--- a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/RawFoilWorkOrderStatusEnum.java
+++ b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/RawFoilWorkOrderStatusEnum.java
@@ -11,9 +11,7 @@ import lombok.Getter;
public enum RawFoilWorkOrderStatusEnum {
START("01","开始"),
- EMPTY_OUT("02","空轴搬出"),
- CONFIRM_VOLUME("03","确认下卷"),
- VOLUME_COMPLETE("04","下卷完成"),
+ EXECUTION("02","执行中"),
END("09","结束");
diff --git a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/StockStatusEnum.java b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/StockStatusEnum.java
new file mode 100644
index 00000000..654d75e1
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/StockStatusEnum.java
@@ -0,0 +1,24 @@
+package cn.code.nl.module.lms.enums;
+
+import lombok.Getter;
+
+/**
+ * @author dsh
+ * 2026/8/4
+ */
+@Getter
+public enum StockStatusEnum {
+
+ YES("1","有货"),
+ NO("2","无货");
+
+
+ private String code;
+
+ private String name;
+
+ StockStatusEnum(String code,String name){
+ this.code = code;
+ this.name = name;
+ }
+}
diff --git a/nl-module-lms/nl-module-lms-server/pom.xml b/nl-module-lms/nl-module-lms-server/pom.xml
index dab9a5e7..4e8ad8e4 100644
--- a/nl-module-lms/nl-module-lms-server/pom.xml
+++ b/nl-module-lms/nl-module-lms-server/pom.xml
@@ -116,6 +116,19 @@
cn.nl.cloud
nl-spring-boot-starter-monitor
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.mockito
+ mockito-core
+
+
+
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/acs/AcsToLmsController.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/acs/AcsToLmsController.java
new file mode 100644
index 00000000..84ebd4ab
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/acs/AcsToLmsController.java
@@ -0,0 +1,36 @@
+package cn.code.nl.module.lms.controller.acs;
+
+import cn.code.nl.framework.common.pojo.CommonResult;
+import cn.code.nl.module.lms.controller.acs.vo.WeighingCompleteReqVO;
+import cn.code.nl.module.lms.service.acs.AcsToLmsService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author dsh
+ * 2026/8/4
+ */
+@Tag(name = "管理后台 - ACS上报LMS")
+@RestController
+@RequestMapping("api/lms/task")
+@Validated
+public class AcsToLmsController {
+
+ @Resource
+ private AcsToLmsService acsToLmsService;
+
+
+ @PostMapping("/apply")
+ @Operation(summary = "ACS上报称重完成")
+ public CommonResult weighingComplete(@Valid @RequestBody WeighingCompleteReqVO weighingCompleteReqVO) {
+ acsToLmsService.weighingComplete(weighingCompleteReqVO);
+ return CommonResult.success(null);
+ }
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/acs/vo/WeighingCompleteReqVO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/acs/vo/WeighingCompleteReqVO.java
new file mode 100644
index 00000000..b7e97290
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/acs/vo/WeighingCompleteReqVO.java
@@ -0,0 +1,25 @@
+package cn.code.nl.module.lms.controller.acs.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @author dsh
+ * 2026/8/4
+ */
+@Data
+public class WeighingCompleteReqVO {
+
+ @Schema(description = "母卷号")
+ @NotNull(message = "母卷号不能为空")
+ private String containerName;
+
+ @Schema(description = "重量")
+ @NotNull(message = "重量不能为空")
+ private BigDecimal productWeight;
+
+
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilcasheposition/RawFoilCashePositionController.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilcasheposition/RawFoilCashePositionController.java
new file mode 100644
index 00000000..413f4474
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilcasheposition/RawFoilCashePositionController.java
@@ -0,0 +1,104 @@
+package cn.code.nl.module.lms.controller.admin.rawfoilcasheposition;
+
+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.lms.controller.admin.rawfoilcasheposition.vo.*;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilcasheposition.RawFoilCashePositionDO;
+import cn.code.nl.module.lms.service.rawfoilcasheposition.RawFoilCashePositionService;
+
+@Tag(name = "管理后台 - 生箔母卷缓存位")
+@RestController
+@RequestMapping("/lms/raw-foil-cashe-position")
+@Validated
+public class RawFoilCashePositionController {
+
+ @Resource
+ private RawFoilCashePositionService rawFoilCashePositionService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建生箔母卷缓存位")
+ @PreAuthorize("@ss.hasPermission('lms:raw-foil-cashe-position:create')")
+ public CommonResult createRawFoilCashePosition(@Valid @RequestBody RawFoilCashePositionSaveReqVO createReqVO) {
+ return success(rawFoilCashePositionService.createRawFoilCashePosition(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新生箔母卷缓存位")
+ @PreAuthorize("@ss.hasPermission('lms:raw-foil-cashe-position:update')")
+ public CommonResult updateRawFoilCashePosition(@Valid @RequestBody RawFoilCashePositionSaveReqVO updateReqVO) {
+ rawFoilCashePositionService.updateRawFoilCashePosition(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除生箔母卷缓存位")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('lms:raw-foil-cashe-position:delete')")
+ public CommonResult deleteRawFoilCashePosition(@RequestParam("id") Long id) {
+ rawFoilCashePositionService.deleteRawFoilCashePosition(id);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete-list")
+ @Parameter(name = "ids", description = "编号", required = true)
+ @Operation(summary = "批量删除生箔母卷缓存位")
+ @PreAuthorize("@ss.hasPermission('lms:raw-foil-cashe-position:delete')")
+ public CommonResult deleteRawFoilCashePositionList(@RequestParam("ids") List ids) {
+ rawFoilCashePositionService.deleteRawFoilCashePositionListByIds(ids);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得生箔母卷缓存位")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('lms:raw-foil-cashe-position:query')")
+ public CommonResult getRawFoilCashePosition(@RequestParam("id") Long id) {
+ RawFoilCashePositionDO rawFoilCashePosition = rawFoilCashePositionService.getRawFoilCashePosition(id);
+ return success(BeanUtils.toBean(rawFoilCashePosition, RawFoilCashePositionRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得生箔母卷缓存位分页")
+ @PreAuthorize("@ss.hasPermission('lms:raw-foil-cashe-position:query')")
+ public CommonResult> getRawFoilCashePositionPage(@Valid RawFoilCashePositionPageReqVO pageReqVO) {
+ PageResult pageResult = rawFoilCashePositionService.getRawFoilCashePositionPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, RawFoilCashePositionRespVO.class));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出生箔母卷缓存位 Excel")
+ @PreAuthorize("@ss.hasPermission('lms:raw-foil-cashe-position:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportRawFoilCashePositionExcel(@Valid RawFoilCashePositionPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = rawFoilCashePositionService.getRawFoilCashePositionPage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "生箔母卷缓存位.xls", "数据", RawFoilCashePositionRespVO.class,
+ BeanUtils.toBean(list, RawFoilCashePositionRespVO.class));
+ }
+
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilcasheposition/vo/RawFoilCashePositionPageReqVO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilcasheposition/vo/RawFoilCashePositionPageReqVO.java
new file mode 100644
index 00000000..524875a6
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilcasheposition/vo/RawFoilCashePositionPageReqVO.java
@@ -0,0 +1,35 @@
+package cn.code.nl.module.lms.controller.admin.rawfoilcasheposition.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.code.nl.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+import static cn.code.nl.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 生箔母卷缓存位分页 Request VO")
+@Data
+public class RawFoilCashePositionPageReqVO extends PageParam {
+
+ @Schema(description = "点位编码")
+ private String pointCode;
+
+ @Schema(description = "母卷号", example = "王五")
+ private String containerName;
+
+ @Schema(description = "入库时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] instorageTime;
+
+ @Schema(description = "生产区域")
+ private String productionArea;
+
+ @Schema(description = "是否启用")
+ private String isUsed;
+
+ @Schema(description = "库存状态", example = "1")
+ private String coolIvtStatus;
+
+}
\ No newline at end of file
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilcasheposition/vo/RawFoilCashePositionRespVO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilcasheposition/vo/RawFoilCashePositionRespVO.java
new file mode 100644
index 00000000..ef236200
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilcasheposition/vo/RawFoilCashePositionRespVO.java
@@ -0,0 +1,87 @@
+package cn.code.nl.module.lms.controller.admin.rawfoilcasheposition.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.*;
+
+@Schema(description = "管理后台 - 生箔母卷缓存位 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class RawFoilCashePositionRespVO {
+
+ @Schema(description = "库存记录标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "30894")
+ @ExcelProperty("库存记录标识")
+ private Long ivtId;
+
+ @Schema(description = "点位编码", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("点位编码")
+ private String pointCode;
+
+ @Schema(description = "母卷号", example = "王五")
+ @ExcelProperty("母卷号")
+ private String containerName;
+
+ @Schema(description = "母卷工单标识", example = "13519")
+ @ExcelProperty("母卷工单标识")
+ private String workorderId;
+
+ @Schema(description = "母卷轴编码")
+ @ExcelProperty("母卷轴编码")
+ private String fullVehicleCode;
+
+ @Schema(description = "入库时间")
+ @ExcelProperty("入库时间")
+ private LocalDateTime instorageTime;
+
+ @Schema(description = "生产区域")
+ @ExcelProperty("生产区域")
+ private String productionArea;
+
+ @Schema(description = "位置")
+ @ExcelProperty("位置")
+ private String pointLocation;
+
+ @Schema(description = "顺序号", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("顺序号")
+ private Integer sortSeq;
+
+ @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("是否启用")
+ private String isUsed;
+
+ @Schema(description = "备注", example = "你说的对")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "创建人", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建人")
+ private String creator;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private String createTime;
+
+ @Schema(description = "修改人")
+ @ExcelProperty("修改人")
+ private String updater;
+
+ @Schema(description = "修改时间")
+ @ExcelProperty("修改时间")
+ private String updateTime;
+
+ @Schema(description = "库存状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @ExcelProperty("库存状态")
+ private String coolIvtStatus;
+
+ @Schema(description = "点位类型", example = "2")
+ @ExcelProperty("点位类型")
+ private String pointType;
+
+ @Schema(description = "是否删除", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("是否删除")
+ private String deleted;
+
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilcasheposition/vo/RawFoilCashePositionSaveReqVO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilcasheposition/vo/RawFoilCashePositionSaveReqVO.java
new file mode 100644
index 00000000..0f9387ce
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilcasheposition/vo/RawFoilCashePositionSaveReqVO.java
@@ -0,0 +1,57 @@
+package cn.code.nl.module.lms.controller.admin.rawfoilcasheposition.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import jakarta.validation.constraints.*;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 生箔母卷缓存位新增/修改 Request VO")
+@Data
+public class RawFoilCashePositionSaveReqVO {
+
+ @Schema(description = "库存记录标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "30894")
+ private Long ivtId;
+
+ @Schema(description = "点位编码", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotEmpty(message = "点位编码不能为空")
+ private String pointCode;
+
+ @Schema(description = "母卷号", example = "王五")
+ private String containerName;
+
+ @Schema(description = "母卷工单标识", example = "13519")
+ private String workorderId;
+
+ @Schema(description = "母卷轴编码")
+ private String fullVehicleCode;
+
+ @Schema(description = "入库时间")
+ private LocalDateTime instorageTime;
+
+ @Schema(description = "生产区域")
+ private String productionArea;
+
+ @Schema(description = "位置")
+ private String pointLocation;
+
+ @Schema(description = "顺序号", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "顺序号不能为空")
+ private Integer sortSeq;
+
+ @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotEmpty(message = "是否启用不能为空")
+ private String isUsed;
+
+ @Schema(description = "备注", example = "你说的对")
+ private String remark;
+
+ @Schema(description = "库存状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotEmpty(message = "库存状态不能为空")
+ private String coolIvtStatus;
+
+ @Schema(description = "点位类型", example = "2")
+ private String pointType;
+
+}
\ No newline at end of file
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilemptyrollercasheposition/RawFoilEmptyRollerCashePositionController.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilemptyrollercasheposition/RawFoilEmptyRollerCashePositionController.java
new file mode 100644
index 00000000..3889dc60
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilemptyrollercasheposition/RawFoilEmptyRollerCashePositionController.java
@@ -0,0 +1,104 @@
+package cn.code.nl.module.lms.controller.admin.rawfoilemptyrollercasheposition;
+
+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.lms.controller.admin.rawfoilemptyrollercasheposition.vo.*;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilemptyrollercasheposition.RawFoilEmptyRollerCashePositionDO;
+import cn.code.nl.module.lms.service.rawfoilemptyrollercasheposition.RawFoilEmptyRollerCashePositionService;
+
+@Tag(name = "管理后台 - 空辊缓存位")
+@RestController
+@RequestMapping("/lms/raw-foil-empty-roller-cashe-position")
+@Validated
+public class RawFoilEmptyRollerCashePositionController {
+
+ @Resource
+ private RawFoilEmptyRollerCashePositionService rawFoilEmptyRollerCashePositionService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建空辊缓存位")
+ @PreAuthorize("@ss.hasPermission('lms:raw-foil-empty-roller-cashe-position:create')")
+ public CommonResult createRawFoilEmptyRollerCashePosition(@Valid @RequestBody RawFoilEmptyRollerCashePositionSaveReqVO createReqVO) {
+ return success(rawFoilEmptyRollerCashePositionService.createRawFoilEmptyRollerCashePosition(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新空辊缓存位")
+ @PreAuthorize("@ss.hasPermission('lms:raw-foil-empty-roller-cashe-position:update')")
+ public CommonResult updateRawFoilEmptyRollerCashePosition(@Valid @RequestBody RawFoilEmptyRollerCashePositionSaveReqVO updateReqVO) {
+ rawFoilEmptyRollerCashePositionService.updateRawFoilEmptyRollerCashePosition(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除空辊缓存位")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('lms:raw-foil-empty-roller-cashe-position:delete')")
+ public CommonResult deleteRawFoilEmptyRollerCashePosition(@RequestParam("id") Long id) {
+ rawFoilEmptyRollerCashePositionService.deleteRawFoilEmptyRollerCashePosition(id);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete-list")
+ @Parameter(name = "ids", description = "编号", required = true)
+ @Operation(summary = "批量删除空辊缓存位")
+ @PreAuthorize("@ss.hasPermission('lms:raw-foil-empty-roller-cashe-position:delete')")
+ public CommonResult deleteRawFoilEmptyRollerCashePositionList(@RequestParam("ids") List ids) {
+ rawFoilEmptyRollerCashePositionService.deleteRawFoilEmptyRollerCashePositionListByIds(ids);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得空辊缓存位")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('lms:raw-foil-empty-roller-cashe-position:query')")
+ public CommonResult getRawFoilEmptyRollerCashePosition(@RequestParam("id") Long id) {
+ RawFoilEmptyRollerCashePositionDO rawFoilEmptyRollerCashePosition = rawFoilEmptyRollerCashePositionService.getRawFoilEmptyRollerCashePosition(id);
+ return success(BeanUtils.toBean(rawFoilEmptyRollerCashePosition, RawFoilEmptyRollerCashePositionRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得空辊缓存位分页")
+ @PreAuthorize("@ss.hasPermission('lms:raw-foil-empty-roller-cashe-position:query')")
+ public CommonResult> getRawFoilEmptyRollerCashePositionPage(@Valid RawFoilEmptyRollerCashePositionPageReqVO pageReqVO) {
+ PageResult pageResult = rawFoilEmptyRollerCashePositionService.getRawFoilEmptyRollerCashePositionPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, RawFoilEmptyRollerCashePositionRespVO.class));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出空辊缓存位 Excel")
+ @PreAuthorize("@ss.hasPermission('lms:raw-foil-empty-roller-cashe-position:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportRawFoilEmptyRollerCashePositionExcel(@Valid RawFoilEmptyRollerCashePositionPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = rawFoilEmptyRollerCashePositionService.getRawFoilEmptyRollerCashePositionPage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "空辊缓存位.xls", "数据", RawFoilEmptyRollerCashePositionRespVO.class,
+ BeanUtils.toBean(list, RawFoilEmptyRollerCashePositionRespVO.class));
+ }
+
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilemptyrollercasheposition/vo/RawFoilEmptyRollerCashePositionPageReqVO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilemptyrollercasheposition/vo/RawFoilEmptyRollerCashePositionPageReqVO.java
new file mode 100644
index 00000000..ee9c0ede
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilemptyrollercasheposition/vo/RawFoilEmptyRollerCashePositionPageReqVO.java
@@ -0,0 +1,25 @@
+package cn.code.nl.module.lms.controller.admin.rawfoilemptyrollercasheposition.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.code.nl.framework.common.pojo.PageParam;
+import java.math.BigDecimal;
+
+@Schema(description = "管理后台 - 空辊缓存位分页 Request VO")
+@Data
+public class RawFoilEmptyRollerCashePositionPageReqVO extends PageParam {
+
+ @Schema(description = "点位编码")
+ private String pointCode;
+
+ @Schema(description = "生产区域")
+ private String productionArea;
+
+ @Schema(description = "是否启用")
+ private String isUsed;
+
+ @Schema(description = "是否有货")
+ private String hasStock;
+
+}
\ No newline at end of file
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilemptyrollercasheposition/vo/RawFoilEmptyRollerCashePositionRespVO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilemptyrollercasheposition/vo/RawFoilEmptyRollerCashePositionRespVO.java
new file mode 100644
index 00000000..180ec7e8
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilemptyrollercasheposition/vo/RawFoilEmptyRollerCashePositionRespVO.java
@@ -0,0 +1,61 @@
+package cn.code.nl.module.lms.controller.admin.rawfoilemptyrollercasheposition.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import java.math.BigDecimal;
+import cn.idev.excel.annotation.*;
+
+@Schema(description = "管理后台 - 空辊缓存位 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class RawFoilEmptyRollerCashePositionRespVO {
+
+ @Schema(description = "点位标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "1242")
+ @ExcelProperty("点位标识")
+ private Long pointId;
+
+ @Schema(description = "点位编码", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("点位编码")
+ private String pointCode;
+
+ @Schema(description = "载具编码")
+ @ExcelProperty("载具编码")
+ private String vehicleCode;
+
+ @Schema(description = "生产区域")
+ @ExcelProperty("生产区域")
+ private String productionArea;
+
+ @Schema(description = "位置")
+ @ExcelProperty("位置")
+ private String pointLocation;
+
+ @Schema(description = "备注", example = "你说的对")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("是否启用")
+ private String isUsed;
+
+ @Schema(description = "修改时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("修改时间")
+ private String updateTime;
+
+ @Schema(description = "重量")
+ @ExcelProperty("重量")
+ private BigDecimal weight;
+
+ @Schema(description = "是否有货", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("是否有货")
+ private String hasStock;
+
+ @Schema(description = "顺序号", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("顺序号")
+ private Integer sortSeq;
+
+ @Schema(description = "点位类型")
+ @ExcelProperty("点位类型")
+ private String pointType;
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilemptyrollercasheposition/vo/RawFoilEmptyRollerCashePositionSaveReqVO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilemptyrollercasheposition/vo/RawFoilEmptyRollerCashePositionSaveReqVO.java
new file mode 100644
index 00000000..0920357d
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/rawfoilemptyrollercasheposition/vo/RawFoilEmptyRollerCashePositionSaveReqVO.java
@@ -0,0 +1,49 @@
+package cn.code.nl.module.lms.controller.admin.rawfoilemptyrollercasheposition.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import jakarta.validation.constraints.*;
+import java.math.BigDecimal;
+
+@Schema(description = "管理后台 - 空辊缓存位新增/修改 Request VO")
+@Data
+public class RawFoilEmptyRollerCashePositionSaveReqVO {
+
+ @Schema(description = "点位标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "1242")
+ private Long pointId;
+
+ @Schema(description = "点位编码", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotEmpty(message = "点位编码不能为空")
+ private String pointCode;
+
+ @Schema(description = "载具编码")
+ private String vehicleCode;
+
+ @Schema(description = "生产区域")
+ private String productionArea;
+
+ @Schema(description = "位置")
+ private String pointLocation;
+
+ @Schema(description = "备注", example = "你说的对")
+ private String remark;
+
+ @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotEmpty(message = "是否启用不能为空")
+ private String isUsed;
+
+ @Schema(description = "重量")
+ private BigDecimal weight;
+
+ @Schema(description = "是否有货", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotEmpty(message = "是否有货不能为空")
+ private String hasStock;
+
+ @Schema(description = "顺序号", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "顺序号不能为空")
+ private Integer sortSeq;
+
+ @Schema(description = "点位类型")
+ private String pointType;
+}
\ No newline at end of file
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/RawFoilController.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/RawFoilController.java
new file mode 100644
index 00000000..c34458de
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/RawFoilController.java
@@ -0,0 +1,42 @@
+package cn.code.nl.module.lms.controller.pda;
+
+import cn.code.nl.framework.common.pojo.CommonResult;
+import cn.code.nl.module.lms.controller.pda.vo.NeedEmptyAxisReqVO;
+import cn.code.nl.module.lms.controller.pda.vo.RawFoilWorkOrderCreateReqVO;
+import cn.code.nl.module.lms.service.pda.RawFoilService;
+import jakarta.validation.Valid;
+import lombok.RequiredArgsConstructor;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import static cn.code.nl.framework.common.pojo.CommonResult.success;
+
+/**
+ * @author dsh
+ * 2026/7/23
+ * 手持-生箔控制层
+ */
+@RestController
+@RequestMapping("/api/pda/rawFoil")
+@RequiredArgsConstructor
+public class RawFoilController {
+
+ private final RawFoilService rawFoilService;
+
+ @PostMapping("/createWorkOrder")
+ @PreAuthorize("@ss.hasPermission('lms:raw-foil-work-order:create')")
+ public CommonResult createWorkOrder(@Valid @RequestBody RawFoilWorkOrderCreateReqVO createReqVO) {
+ return success(rawFoilService.createWorkOrder(createReqVO));
+ }
+
+ @PostMapping("/needEmptyAxis")
+ @PreAuthorize("@ss.hasPermission('lms:raw-foil-work-order:query')")
+ public CommonResult needEmptyAxis(@Valid @RequestBody NeedEmptyAxisReqVO needEmptyAxisReqVO) {
+ rawFoilService.needEmptyAxis(needEmptyAxisReqVO);
+ return success(true);
+ }
+
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/vo/NeedEmptyAxisReqVO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/vo/NeedEmptyAxisReqVO.java
new file mode 100644
index 00000000..270534e3
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/vo/NeedEmptyAxisReqVO.java
@@ -0,0 +1,18 @@
+package cn.code.nl.module.lms.controller.pda.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+/**
+ * @author dsh
+ * 2026/7/24
+ */
+@Schema(description = "手持 - 生箔工序工单 呼叫-上满下空")
+@Data
+public class NeedEmptyAxisReqVO {
+
+ @Schema(description = "工单标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "4374")
+ @NotNull(message = "生箔工序工单标识不能为空")
+ private Long workorderId;
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/pda/controller/rawfoil/vo/RawFoilWorkOrderCreateReqVO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/vo/RawFoilWorkOrderCreateReqVO.java
similarity index 96%
rename from nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/pda/controller/rawfoil/vo/RawFoilWorkOrderCreateReqVO.java
rename to nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/vo/RawFoilWorkOrderCreateReqVO.java
index 9b046cc3..110b5d85 100644
--- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/pda/controller/rawfoil/vo/RawFoilWorkOrderCreateReqVO.java
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/vo/RawFoilWorkOrderCreateReqVO.java
@@ -1,7 +1,8 @@
-package cn.code.nl.module.lms.pda.controller.rawfoil.vo;
+package cn.code.nl.module.lms.controller.pda.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
+import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@@ -11,6 +12,7 @@ import java.time.LocalDateTime;
* 2026/7/23
*/
@Schema(description = "手持 - 生箔工序工单新增 Request VO")
+@Data
public class RawFoilWorkOrderCreateReqVO {
@Schema(description = "母卷号", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/rawfoilcasheposition/RawFoilCashePositionDO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/rawfoilcasheposition/RawFoilCashePositionDO.java
new file mode 100644
index 00000000..28961f60
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/rawfoilcasheposition/RawFoilCashePositionDO.java
@@ -0,0 +1,82 @@
+package cn.code.nl.module.lms.dal.dataobject.rawfoilcasheposition;
+
+import lombok.*;
+import java.util.*;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.code.nl.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 生箔母卷缓存位 DO
+ *
+ * @author 诺力管理员
+ */
+@TableName("lms_rawfoil_casheposition")
+@KeySequence("lms_rawfoil_casheposition_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class RawFoilCashePositionDO extends BaseDO {
+
+ /**
+ * 库存记录标识
+ */
+ @TableId
+ private Long ivtId;
+ /**
+ * 点位编码
+ */
+ private String pointCode;
+ /**
+ * 母卷号
+ */
+ private String containerName;
+ /**
+ * 母卷工单标识
+ */
+ private String workorderId;
+ /**
+ * 母卷轴编码
+ */
+ private String fullVehicleCode;
+ /**
+ * 入库时间
+ */
+ private LocalDateTime instorageTime;
+ /**
+ * 生产区域
+ */
+ private String productionArea;
+ /**
+ * 位置
+ */
+ private String pointLocation;
+ /**
+ * 顺序号
+ */
+ private Integer sortSeq;
+ /**
+ * 是否启用
+ */
+ private String isUsed;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 库存状态
+ */
+ private String coolIvtStatus;
+ /**
+ * 点位类型
+ */
+ private String pointType;
+
+ /**
+ * 锁(0.空闲,1占用)
+ */
+ private String lockStatus;
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/rawfoilemptyrollercasheposition/RawFoilEmptyRollerCashePositionDO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/rawfoilemptyrollercasheposition/RawFoilEmptyRollerCashePositionDO.java
new file mode 100644
index 00000000..19a3490f
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/rawfoilemptyrollercasheposition/RawFoilEmptyRollerCashePositionDO.java
@@ -0,0 +1,75 @@
+package cn.code.nl.module.lms.dal.dataobject.rawfoilemptyrollercasheposition;
+
+import lombok.*;
+import java.util.*;
+import java.math.BigDecimal;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.code.nl.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 空辊缓存位 DO
+ *
+ * @author 诺力管理员
+ */
+@TableName("lms_rawfoil_emptyroller_casheposition")
+@KeySequence("lms_rawfoil_emptyroller_casheposition_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class RawFoilEmptyRollerCashePositionDO extends BaseDO {
+
+ /**
+ * 点位标识
+ */
+ @TableId
+ private Long pointId;
+ /**
+ * 点位编码
+ */
+ private String pointCode;
+ /**
+ * 载具编码
+ */
+ private String vehicleCode;
+ /**
+ * 生产区域
+ */
+ private String productionArea;
+ /**
+ * 位置
+ */
+ private String pointLocation;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 是否启用
+ */
+ private String isUsed;
+ /**
+ * 重量
+ */
+ private BigDecimal weight;
+ /**
+ * 是否有货
+ */
+ private String hasStock;
+ /**
+ * 顺序号
+ */
+ private Integer sortSeq;
+
+ /**
+ * 点位类型
+ */
+ private String pointType;
+
+ /**
+ * 锁(0.空闲,1占用)
+ */
+ private String lockStatus;
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/rawfoilpointivt/RawFoilPointIVTDO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/rawfoilpointivt/RawFoilPointIVTDO.java
index a6c12b50..b2faa315 100644
--- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/rawfoilpointivt/RawFoilPointIVTDO.java
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/rawfoilpointivt/RawFoilPointIVTDO.java
@@ -53,4 +53,8 @@ public class RawFoilPointIVTDO extends BaseDO {
*/
private String isUsed;
+ /**
+ * 锁(0.空闲,1占用)
+ */
+ private String lockStatus;
}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/rawfoilcasheposition/RawFoilCashePositionMapper.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/rawfoilcasheposition/RawFoilCashePositionMapper.java
new file mode 100644
index 00000000..cd27b058
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/rawfoilcasheposition/RawFoilCashePositionMapper.java
@@ -0,0 +1,121 @@
+package cn.code.nl.module.lms.dal.mysql.rawfoilcasheposition;
+
+import java.time.LocalDateTime;
+import java.util.*;
+
+import cn.code.nl.framework.common.enums.CommonStatusEnum;
+import cn.code.nl.framework.common.pojo.PageResult;
+import cn.code.nl.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.code.nl.framework.mybatis.core.mapper.BaseMapperX;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilcasheposition.RawFoilCashePositionDO;
+import cn.code.nl.module.lms.enums.LockStatusEnum;
+import cn.code.nl.module.lms.enums.RawFoilCashePositionTypeEnum;
+import org.apache.ibatis.annotations.Mapper;
+import cn.code.nl.module.lms.controller.admin.rawfoilcasheposition.vo.*;
+
+/**
+ * 生箔母卷缓存位 Mapper
+ *
+ * @author 诺力管理员
+ */
+@Mapper
+public interface RawFoilCashePositionMapper extends BaseMapperX {
+
+ default PageResult selectPage(RawFoilCashePositionPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .eqIfPresent(RawFoilCashePositionDO::getPointCode, reqVO.getPointCode())
+ .likeIfPresent(RawFoilCashePositionDO::getContainerName, reqVO.getContainerName())
+ .betweenIfPresent(RawFoilCashePositionDO::getInstorageTime, reqVO.getInstorageTime())
+ .eqIfPresent(RawFoilCashePositionDO::getProductionArea, reqVO.getProductionArea())
+ .eqIfPresent(RawFoilCashePositionDO::getIsUsed, reqVO.getIsUsed())
+ .eqIfPresent(RawFoilCashePositionDO::getCoolIvtStatus, reqVO.getCoolIvtStatus())
+ .orderByDesc(RawFoilCashePositionDO::getIvtId));
+ }
+
+ /**
+ * 根据点位类型查询空闲且未占用的候选点位列表
+ * 筛选条件:点位类型、已启用、无母卷、未占用,按顺序号升序(越小离称重位越近)
+ *
+ * @param pointType 点位类型
+ * @return 候选点位列表
+ */
+ default List selectEmptyPositionList(String pointType) {
+ return selectList(new LambdaQueryWrapperX()
+ .eq(RawFoilCashePositionDO::getPointType, pointType)
+ .eq(RawFoilCashePositionDO::getIsUsed, CommonStatusEnum.DISABLE.getStatus())
+ .and(w -> w.isNull(RawFoilCashePositionDO::getContainerName)
+ .or().eq(RawFoilCashePositionDO::getContainerName, ""))
+ .eq(RawFoilCashePositionDO::getLockStatus, LockStatusEnum.IDLE.getCode())
+ .orderByAsc(RawFoilCashePositionDO::getSortSeq));
+ }
+
+ /**
+ * CAS 占用候选点位:仅当点位空闲时更新为占用
+ *
+ * @param ivtId 库存记录标识
+ * @return 影响行数,大于 0 表示抢占成功
+ */
+ default int lockPosition(Long ivtId) {
+ RawFoilCashePositionDO updateObj = new RawFoilCashePositionDO();
+ updateObj.setLockStatus(LockStatusEnum.OCCUPIED.getCode());
+ return update(updateObj, new LambdaUpdateWrapper()
+ .eq(RawFoilCashePositionDO::getIvtId, ivtId)
+ .eq(RawFoilCashePositionDO::getLockStatus, LockStatusEnum.IDLE.getCode()));
+ }
+
+ /**
+ * 释放点位占用:仅当点位被占用时更新为空闲
+ *
+ * @param pointCode 点位编码
+ * @return 影响行数,0 表示点位已释放(幂等)
+ */
+ default int releaseLockByPointCode(String pointCode) {
+ RawFoilCashePositionDO updateObj = new RawFoilCashePositionDO();
+ updateObj.setLockStatus(LockStatusEnum.IDLE.getCode());
+ return update(updateObj, new LambdaUpdateWrapper()
+ .eq(RawFoilCashePositionDO::getPointCode, pointCode)
+ .eq(RawFoilCashePositionDO::getLockStatus, LockStatusEnum.OCCUPIED.getCode()));
+ }
+
+ /**
+ * 母卷入库:仅当点位被占用且无母卷时写入母卷信息并释放占用
+ *
+ * @param pointCode 点位编码
+ * @param containerName 母卷号
+ * @param workorderId 母卷工单标识(可为空)
+ * @param instorageTime 入库时间
+ * @return 影响行数,0 表示已入库或已释放(幂等)
+ */
+ default int instoragePosition(String pointCode, String containerName, String workorderId,
+ LocalDateTime instorageTime) {
+ RawFoilCashePositionDO updateObj = new RawFoilCashePositionDO();
+ updateObj.setContainerName(containerName);
+ updateObj.setWorkorderId(workorderId);
+ updateObj.setInstorageTime(instorageTime);
+ updateObj.setLockStatus(LockStatusEnum.IDLE.getCode());
+ return update(updateObj, new LambdaUpdateWrapper()
+ .eq(RawFoilCashePositionDO::getPointCode, pointCode)
+ .eq(RawFoilCashePositionDO::getLockStatus, LockStatusEnum.OCCUPIED.getCode())
+ .and(w -> w.isNull(RawFoilCashePositionDO::getContainerName)
+ .or().eq(RawFoilCashePositionDO::getContainerName, "")));
+ }
+
+ /**
+ * 母卷出库:清空起点点位上的母卷记录
+ * 仅当母卷号匹配时清空,防止重复回调误清已新入库的母卷,天然幂等
+ *
+ * @param pointCode 点位编码
+ * @param containerName 母卷号
+ * @return 影响行数,0 表示点位上无该母卷(幂等)
+ */
+ default int outstockPosition(String pointCode, String containerName) {
+ return update(null, new LambdaUpdateWrapper()
+ .set(RawFoilCashePositionDO::getContainerName, null)
+ .set(RawFoilCashePositionDO::getWorkorderId, null)
+ .set(RawFoilCashePositionDO::getInstorageTime, null)
+ .eq(RawFoilCashePositionDO::getPointCode, pointCode)
+ .eq(RawFoilCashePositionDO::getContainerName, containerName));
+ }
+
+}
\ No newline at end of file
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/rawfoilemptyrollercasheposition/RawFoilEmptyRollerCashePositionMapper.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/rawfoilemptyrollercasheposition/RawFoilEmptyRollerCashePositionMapper.java
new file mode 100644
index 00000000..86856563
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/rawfoilemptyrollercasheposition/RawFoilEmptyRollerCashePositionMapper.java
@@ -0,0 +1,87 @@
+package cn.code.nl.module.lms.dal.mysql.rawfoilemptyrollercasheposition;
+
+import java.util.*;
+
+import cn.code.nl.framework.common.enums.CommonStatusEnum;
+import cn.code.nl.framework.common.pojo.PageResult;
+import cn.code.nl.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.code.nl.framework.mybatis.core.mapper.BaseMapperX;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilcasheposition.RawFoilCashePositionDO;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilemptyrollercasheposition.RawFoilEmptyRollerCashePositionDO;
+import cn.code.nl.module.lms.enums.EmptyRollerPointTypeEnum;
+import cn.code.nl.module.lms.enums.LockStatusEnum;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import org.apache.ibatis.annotations.Mapper;
+import cn.code.nl.module.lms.controller.admin.rawfoilemptyrollercasheposition.vo.*;
+
+/**
+ * 空辊缓存位 Mapper
+ *
+ * @author 诺力管理员
+ */
+@Mapper
+public interface RawFoilEmptyRollerCashePositionMapper extends BaseMapperX {
+
+ default PageResult selectPage(RawFoilEmptyRollerCashePositionPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .likeIfPresent(RawFoilEmptyRollerCashePositionDO::getPointCode, reqVO.getPointCode())
+ .eqIfPresent(RawFoilEmptyRollerCashePositionDO::getProductionArea, reqVO.getProductionArea())
+ .eqIfPresent(RawFoilEmptyRollerCashePositionDO::getIsUsed, reqVO.getIsUsed())
+ .eqIfPresent(RawFoilEmptyRollerCashePositionDO::getHasStock, reqVO.getHasStock())
+ .orderByDesc(RawFoilEmptyRollerCashePositionDO::getPointId));
+ }
+
+ /**
+ * 根据点位类型获取空辊缓存位等待点
+ * @param pointType 点位类型 3:生箔空辊等待点 4:分切空辊等待点
+ * @return RawFoilEmptyRollerCashePositionDO
+ */
+ default RawFoilEmptyRollerCashePositionDO selectEmptyRollerWaitPointByPointType(String pointType){
+ return selectOne(RawFoilEmptyRollerCashePositionDO::getPointType, pointType,
+ RawFoilEmptyRollerCashePositionDO::getIsUsed, CommonStatusEnum.DISABLE.getStatus());
+ }
+
+ /**
+ * 根据点位类型查询空闲且未占用的候选点位列表
+ * 筛选条件:点位类型、已启用、有货无货、未占用,按顺序号降序
+ *
+ * @param pointType 点位类型, hasStock 是否有货
+ * @return 候选点位列表
+ */
+ default List selectEmptyPositionList(String pointType,String hasStock){
+ return selectList(new LambdaQueryWrapperX()
+ .eq(RawFoilEmptyRollerCashePositionDO::getHasStock,hasStock)
+ .eq(RawFoilEmptyRollerCashePositionDO::getPointType,pointType)
+ .eq(RawFoilEmptyRollerCashePositionDO::getIsUsed,CommonStatusEnum.DISABLE.getStatus())
+ .eq(RawFoilEmptyRollerCashePositionDO::getLockStatus,LockStatusEnum.IDLE.getCode())
+ .orderByDesc(RawFoilEmptyRollerCashePositionDO::getSortSeq)
+ );
+ }
+
+
+// default List selectEmptyPositionList(String pointType) {
+// return selectList(new LambdaQueryWrapperX()
+// .eq(RawFoilCashePositionDO::getPointType, pointType)
+// .eq(RawFoilCashePositionDO::getIsUsed, CommonStatusEnum.DISABLE.getStatus())
+// .and(w -> w.isNull(RawFoilCashePositionDO::getContainerName)
+// .or().eq(RawFoilCashePositionDO::getContainerName, ""))
+// .eq(RawFoilCashePositionDO::getLockStatus, LockStatusEnum.IDLE.getCode())
+// .orderByAsc(RawFoilCashePositionDO::getSortSeq));
+// }
+
+ /**
+ * CAS 占用候选点位:仅当点位空闲时更新为占用
+ *
+ * @param pointId 点位标识
+ * @return 影响行数,大于 0 表示抢占成功
+ */
+ default int lockPosition(Long pointId){
+ RawFoilEmptyRollerCashePositionDO updateObj = new RawFoilEmptyRollerCashePositionDO();
+ updateObj.setLockStatus(LockStatusEnum.OCCUPIED.getCode());
+ return update(updateObj, new LambdaUpdateWrapper<>(RawFoilEmptyRollerCashePositionDO.class)
+ .eq(RawFoilEmptyRollerCashePositionDO::getPointId,pointId)
+ .eq(RawFoilEmptyRollerCashePositionDO::getLockStatus,LockStatusEnum.IDLE.getCode())
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/rawfoilpointivt/RawFoilPointIVTMapper.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/rawfoilpointivt/RawFoilPointIVTMapper.java
index cca904d0..6c939454 100644
--- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/rawfoilpointivt/RawFoilPointIVTMapper.java
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/rawfoilpointivt/RawFoilPointIVTMapper.java
@@ -6,6 +6,8 @@ import cn.code.nl.framework.common.pojo.PageResult;
import cn.code.nl.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.code.nl.framework.mybatis.core.mapper.BaseMapperX;
import cn.code.nl.module.lms.dal.dataobject.rawfoilpointivt.RawFoilPointIVTDO;
+import cn.code.nl.module.lms.enums.LockStatusEnum;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper;
import cn.code.nl.module.lms.controller.admin.rawfoilpointivt.vo.*;
@@ -37,4 +39,32 @@ public interface RawFoilPointIVTMapper extends BaseMapperX {
return selectOne(RawFoilPointIVTDO::getPointCode,pointCode);
}
+ /**
+ * CAS 占用生箔机点位:仅当点位空闲时更新为占用
+ *
+ * @param pointId 点位标识
+ * @return 影响行数,大于 0 表示抢占成功
+ */
+ default int lockPoint(Long pointId) {
+ RawFoilPointIVTDO updateObj = new RawFoilPointIVTDO();
+ updateObj.setLockStatus(LockStatusEnum.OCCUPIED.getCode());
+ return update(updateObj, new LambdaUpdateWrapper()
+ .eq(RawFoilPointIVTDO::getPointId, pointId)
+ .eq(RawFoilPointIVTDO::getLockStatus, LockStatusEnum.IDLE.getCode()));
+ }
+
+ /**
+ * 释放生箔机点位占用:仅当点位被占用时更新为空闲
+ *
+ * @param pointCode 点位编码
+ * @return 影响行数,0 表示点位已释放(幂等)
+ */
+ default int releaseLockByPointCode(String pointCode) {
+ RawFoilPointIVTDO updateObj = new RawFoilPointIVTDO();
+ updateObj.setLockStatus(LockStatusEnum.IDLE.getCode());
+ return update(updateObj, new LambdaUpdateWrapper()
+ .eq(RawFoilPointIVTDO::getPointCode, pointCode)
+ .eq(RawFoilPointIVTDO::getLockStatus, LockStatusEnum.OCCUPIED.getCode()));
+ }
+
}
\ No newline at end of file
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/acs/AcsToLmsService.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/acs/AcsToLmsService.java
new file mode 100644
index 00000000..fa6680ec
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/acs/AcsToLmsService.java
@@ -0,0 +1,16 @@
+package cn.code.nl.module.lms.service.acs;
+
+import cn.code.nl.framework.common.pojo.CommonResult;
+import cn.code.nl.module.lms.controller.acs.vo.WeighingCompleteReqVO;
+
+/**
+ * @author dsh
+ * 2026/8/4
+ */
+public interface AcsToLmsService {
+
+ /**
+ * 称重完成
+ */
+ void weighingComplete(WeighingCompleteReqVO weighingCompleteReqVO);
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/acs/AcsToLmsServiceImpl.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/acs/AcsToLmsServiceImpl.java
new file mode 100644
index 00000000..629f1c02
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/acs/AcsToLmsServiceImpl.java
@@ -0,0 +1,134 @@
+package cn.code.nl.module.lms.service.acs;
+
+import cn.code.nl.framework.common.pojo.CommonResult;
+import cn.code.nl.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.code.nl.module.lms.controller.acs.vo.WeighingCompleteReqVO;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilcasheposition.RawFoilCashePositionDO;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilworkorder.RawFoilWorkOrderDO;
+import cn.code.nl.module.lms.dal.mysql.rawfoilcasheposition.RawFoilCashePositionMapper;
+import cn.code.nl.module.lms.dal.mysql.rawfoilworkorder.RawFoilWorkOrderMapper;
+import cn.code.nl.module.lms.enums.RawFoilCashePositionTypeEnum;
+import cn.code.nl.module.lms.enums.RawFoilHandleCodeConstants;
+import cn.code.nl.module.lms.enums.RawFoilWorkOrderStatusEnum;
+import cn.code.nl.module.lms.service.rawfoilcasheposition.RawFoilCashePositionService;
+import cn.code.nl.module.task.api.TransportTaskApi;
+import cn.code.nl.module.task.dto.TaskInfoDTO;
+import cn.code.nl.module.task.dto.TransportTaskCreateReqDTO;
+import cn.code.nl.module.task.enums.AcsTaskTypeEnum;
+import cn.code.nl.module.task.enums.TaskOwnerServiceEnum;
+import cn.code.nl.module.task.enums.TaskTypeEnum;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.UUID;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.code.nl.module.lms.enums.ErrorCodeConstants.*;
+
+/**
+ * ACS 上报 LMS 服务实现类
+ *
+ * @author dsh
+ * 2026/8/5
+ */
+@Slf4j
+@Service
+public class AcsToLmsServiceImpl implements AcsToLmsService {
+
+ @Resource
+ private TransportTaskApi transportTaskApi;
+
+ @Resource
+ private RawFoilWorkOrderMapper rawFoilWorkOrderMapper;
+
+ @Resource
+ private RawFoilCashePositionMapper rawFoilCashePositionMapper;
+
+ @Resource
+ private RawFoilCashePositionService rawFoilCashePositionService;
+
+ /**
+ * ACS 上报称重完成:校验后更新工单重量,创建母卷从称重位到常规缓存位的入库搬运任务
+ *
+ * @param weighingCompleteReqVO 称重完成请求信息
+ */
+ @Override
+ public void weighingComplete(WeighingCompleteReqVO weighingCompleteReqVO) {
+ String containerName = weighingCompleteReqVO.getContainerName();
+
+ // 1. 根据母卷号查询生箔工单
+ RawFoilWorkOrderDO workOrder = rawFoilWorkOrderMapper.selectByContainerNameAndNotEndStatus(containerName);
+ if (workOrder == null) {
+ throw exception(RAW_FOIL_WORK_ORDER_NOT_EXISTS);
+ }
+ // 2. 校验工单状态为执行中(称重完成只可能发生在需要空轴任务下发之后)
+// if (!RawFoilWorkOrderStatusEnum.EXECUTION.getCode().equals(workOrder.getStatus())) {
+// throw exception(RAW_FOIL_WORK_ORDER_STATUS_NOT_EXECUTION);
+// }
+ // 3. 幂等校验:母卷存在在途搬运任务则拒绝(拦截任务执行期间的重复上报)
+ CommonResult> runningResult = transportTaskApi
+ .getRunningTaskByMaterialCode(containerName, TaskOwnerServiceEnum.LMS.getCode());
+ if (runningResult.isError()) {
+ log.error("查询在途搬运任务失败, containerName={}, 返回={}", containerName, runningResult);
+ throw exception(RAW_FOIL_WORK_ORDER_FAIL);
+ }
+ if (CollUtil.isNotEmpty(runningResult.getData())) {
+ throw exception(RAW_FOIL_WORK_ORDER_NOT_SELECT);
+ }
+ // 4. 起点:称重位
+ List weighingPositions = rawFoilCashePositionMapper.selectList(
+ new LambdaQueryWrapperX()
+ .eq(RawFoilCashePositionDO::getPointType,
+ RawFoilCashePositionTypeEnum.WEIGHING_POSITION.getCode()));
+ if (CollUtil.isEmpty(weighingPositions)) {
+ throw exception(RAW_FOIL_WEIGHING_POSITION_NOT_EXISTS);
+ }
+ RawFoilCashePositionDO weighingPosition = weighingPositions.get(0);
+
+ // 5. 校验母卷在称重位
+ if (!containerName.equals(weighingPosition.getContainerName())) {
+ throw exception(RAW_FOIL_CONTAINER_NOT_ON_WEIGHING_POSITION);
+ }
+
+ // 6. 更新生箔工单重量
+ RawFoilWorkOrderDO weightUpdate = new RawFoilWorkOrderDO();
+ weightUpdate.setWorkorderId(workOrder.getWorkorderId());
+ weightUpdate.setProductWeight(weighingCompleteReqVO.getProductWeight());
+ rawFoilWorkOrderMapper.updateById(weightUpdate);
+
+ // 7. 终点:分配常规缓存位并 CAS 占用
+ RawFoilCashePositionDO conventionalPosition = rawFoilCashePositionService.allocateConventionalPosition();
+
+ // 8. 创建入库搬运任务;失败必须补偿释放已占用的常规位,否则点位死锁
+ try {
+ TransportTaskCreateReqDTO reqDTO = new TransportTaskCreateReqDTO();
+ reqDTO.setTaskName(UUID.randomUUID().toString());
+ reqDTO.setOwnerService(TaskOwnerServiceEnum.LMS.getCode());
+ reqDTO.setHandleCode(RawFoilHandleCodeConstants.RAW_FOIL_INSTORAGE_TASK);
+ reqDTO.setAcsTaskType(AcsTaskTypeEnum.TRUSS_TASK.getCode());
+ reqDTO.setAgvSystemType("1");
+ reqDTO.setPointCode1(weighingPosition.getPointCode());
+ reqDTO.setPointCode2(conventionalPosition.getPointCode());
+ reqDTO.setMaterialCode(containerName);
+ reqDTO.setPriority("1");
+ reqDTO.setProductArea(workOrder.getProductionArea());
+ reqDTO.setIsAutoIssue("1");
+ reqDTO.setIsCreateFinish(true);
+ reqDTO.setTaskType(TaskTypeEnum.RAW_FOIL_INSTORAGE_TASK.getCode());
+
+ CommonResult taskResult = transportTaskApi.createTransportTask(reqDTO);
+ if (taskResult.isError()) {
+ log.error("创建生箔入库任务失败, containerName={}, reqDTO={}, 返回={}",
+ containerName, reqDTO, taskResult);
+ throw exception(RAW_FOIL_TRANSPORT_TASK_CREATE_FAIL);
+ }
+ } catch (Exception e) {
+ // 补偿释放:常规缓存位
+ rawFoilCashePositionService.releasePositionLock(conventionalPosition.getPointCode());
+ throw e;
+ }
+ }
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/pda/RawFoilService.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/pda/RawFoilService.java
new file mode 100644
index 00000000..3822e4c3
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/pda/RawFoilService.java
@@ -0,0 +1,24 @@
+package cn.code.nl.module.lms.service.pda;
+
+import cn.code.nl.module.lms.controller.pda.vo.NeedEmptyAxisReqVO;
+import cn.code.nl.module.lms.controller.pda.vo.RawFoilWorkOrderCreateReqVO;
+
+/**
+ * @author dsh
+ * 2026/7/23
+ * 手持 - 生箔服务
+ */
+public interface RawFoilService {
+
+ /**
+ * 手持 - 创建生箔工序工单
+ * @param createReqVO
+ * @return Long
+ */
+ Long createWorkOrder(RawFoilWorkOrderCreateReqVO createReqVO);
+
+ /**
+ * 手持 - 呼叫 上满下空
+ */
+ void needEmptyAxis(NeedEmptyAxisReqVO needEmptyAxisReqVO);
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/pda/RawFoilServiceImpl.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/pda/RawFoilServiceImpl.java
new file mode 100644
index 00000000..147ba1f1
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/pda/RawFoilServiceImpl.java
@@ -0,0 +1,172 @@
+package cn.code.nl.module.lms.service.pda;
+
+import cn.code.nl.framework.common.enums.CommonStatusEnum;
+import cn.code.nl.framework.common.pojo.CommonResult;
+import cn.code.nl.framework.common.util.object.BeanUtils;
+import cn.code.nl.module.base.api.materialbase.MaterialBaseApi;
+import cn.code.nl.module.base.api.materialbase.dto.MaterialBaseRespDTO;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilcasheposition.RawFoilCashePositionDO;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilemptyrollercasheposition.RawFoilEmptyRollerCashePositionDO;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilpointivt.RawFoilPointIVTDO;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilworkorder.RawFoilWorkOrderDO;
+import cn.code.nl.module.lms.dal.mysql.rawfoilemptyrollercasheposition.RawFoilEmptyRollerCashePositionMapper;
+import cn.code.nl.module.lms.dal.mysql.rawfoilpointivt.RawFoilPointIVTMapper;
+import cn.code.nl.module.lms.dal.mysql.rawfoilworkorder.RawFoilWorkOrderMapper;
+import cn.code.nl.module.lms.enums.*;
+import cn.code.nl.module.lms.service.rawfoilcasheposition.RawFoilCashePositionService;
+import cn.code.nl.module.lms.service.rawfoilpointivt.RawFoilPointIVTService;
+import cn.code.nl.module.task.enums.AcsTaskTypeEnum;
+import cn.code.nl.module.lms.controller.pda.vo.NeedEmptyAxisReqVO;
+import cn.code.nl.module.lms.controller.pda.vo.RawFoilWorkOrderCreateReqVO;
+import cn.code.nl.module.task.api.TransportTaskApi;
+import cn.code.nl.module.task.dto.TransportTaskCreateReqDTO;
+import cn.code.nl.module.task.enums.TaskOwnerServiceEnum;
+import cn.code.nl.module.task.enums.TaskTypeEnum;
+import cn.hutool.core.lang.UUID;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.ObjectUtil;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.code.nl.module.lms.enums.ErrorCodeConstants.*;
+
+/**
+ * @author dsh
+ * 2026/7/23
+ */
+@Slf4j
+@Service
+public class RawFoilServiceImpl implements RawFoilService{
+
+ @Resource
+ private RawFoilWorkOrderMapper rawFoilWorkOrderMapper;
+
+ @Resource
+ private MaterialBaseApi materialBaseApi;
+
+ @Resource
+ private RawFoilPointIVTMapper rawFoilPointIVTMapper;
+
+ @Resource
+ private RawFoilEmptyRollerCashePositionMapper rawFoilEmptyRollerCashePositionMapper;
+
+ @Resource
+ private TransportTaskApi transportTaskApi;
+
+ @Resource
+ private RawFoilCashePositionService rawFoilCashePositionService;
+
+ @Resource
+ private RawFoilPointIVTService rawFoilPointIVTService;
+
+ @Override
+ public Long createWorkOrder(RawFoilWorkOrderCreateReqVO createReqVO) {
+
+ RawFoilWorkOrderDO rawFoilWorkOrder = BeanUtils.toBean(createReqVO, RawFoilWorkOrderDO.class);
+
+ // 校验是否存在相同母卷号未结束的生箔工序工单
+ RawFoilWorkOrderDO rawFoilWorkOrderDO = rawFoilWorkOrderMapper.selectByContainerNameAndNotEndStatus(rawFoilWorkOrder.getContainerName());
+ if (ObjectUtil.isNotEmpty(rawFoilWorkOrderDO)){
+ throw exception(RAW_FOIL_WORK_ORDER_CONTAINER_NAME_EXISTS);
+ }
+
+ //校验生箔机点位是否存在
+ RawFoilPointIVTDO rawFoilPointIVTDO = rawFoilPointIVTMapper.selectByPointCode(rawFoilWorkOrder.getPointCode());
+ if (ObjectUtil.isEmpty(rawFoilPointIVTDO)){
+ throw exception(RAW_FOIL_WORK_ORDER_POINT_CODE_NOT_EXISTS);
+ }
+
+ //判断物料是否存在
+ //远程调用物料API
+ CommonResult result = materialBaseApi.getMaterialBaseByCode(rawFoilWorkOrder.getProductCode());
+ // 判断是否访问成功 || 是否存在物料数据 || 物料是否已启用
+ if (result.isError() || ObjectUtil.isEmpty(result.getData()) || String.valueOf(CommonStatusEnum.ENABLE.getStatus()).equals(result.getData().getIsUsed())){
+ throw exception(RAW_FOIL_WORK_ORDER_MATERIAL_NOT_EXISTS);
+ }
+
+ rawFoilWorkOrder.setWorkorderId(IdUtil.getSnowflakeNextId());
+ rawFoilWorkOrder.setProductionArea(rawFoilPointIVTDO.getProductionArea());
+ rawFoilWorkOrder.setStatus(RawFoilWorkOrderStatusEnum.START.getCode());
+
+ // 插入
+ rawFoilWorkOrderMapper.insert(rawFoilWorkOrder);
+
+ // 返回
+ return rawFoilWorkOrder.getWorkorderId();
+ }
+
+ @Override
+ public void needEmptyAxis(NeedEmptyAxisReqVO needEmptyAxisReqVO) {
+
+ RawFoilWorkOrderDO rawFoilWorkOrderDO = rawFoilWorkOrderMapper.selectById(needEmptyAxisReqVO.getWorkorderId());
+
+ // 校验工单是否存在
+ if (ObjectUtil.isEmpty(rawFoilWorkOrderDO)){
+ throw exception(RAW_FOIL_WORK_ORDER_NOT_EXISTS);
+ }
+
+ // 校验生箔工序工单状态
+ if (!RawFoilWorkOrderStatusEnum.START.getCode().equals(rawFoilWorkOrderDO.getStatus())){
+ throw exception(RAW_FOIL_WORK_ORDER_STATUS_NOT_START);
+ }
+
+ // 分配下满上空任务点位
+ // 1.分配空辊站点 分配规则:按顺序分配 需要二次分配 先下发等待点
+ // 2.分配生箔机下料位
+ // 3.分配生箔机上空辊点位
+ // 4.分配母卷下料位 分配规则:称重位>称重缓存位>母卷缓存位离称重位近的点位优先
+
+ // 校验是否存在空辊等待点
+ RawFoilEmptyRollerCashePositionDO emptyRollerCashePositionDO = rawFoilEmptyRollerCashePositionMapper.selectEmptyRollerWaitPointByPointType(EmptyRollerPointTypeEnum.RAW_FOIL_EMPTY_ROLLER_WAIT_POINT.getCode());
+ if (ObjectUtil.isEmpty(emptyRollerCashePositionDO)){
+ throw exception(EMPTY_ROLLER_CASHE_POSITION_WAIT_POINT_NOT_EXISTS);
+ }
+
+ // 分配并占用生箔机点位(校验点位存在、已启用;CAS 占用,抢占失败抛出点位被占用异常)
+ RawFoilPointIVTDO rawFoilPointIVTDO = rawFoilPointIVTService.allocatePoint(rawFoilWorkOrderDO.getPointCode());
+
+ TransportTaskCreateReqDTO reqDTO = new TransportTaskCreateReqDTO();
+ reqDTO.setTaskName(UUID.randomUUID().toString());
+ reqDTO.setOwnerService(TaskOwnerServiceEnum.LMS.getCode());
+ reqDTO.setHandleCode(RawFoilHandleCodeConstants.RAW_FOIL_TASK);
+ reqDTO.setAcsTaskType(AcsTaskTypeEnum.TRUSS_TASK.getCode());
+ reqDTO.setAgvSystemType("1");
+ reqDTO.setPointCode1(emptyRollerCashePositionDO.getPointCode());
+ reqDTO.setPointCode2(rawFoilPointIVTDO.getPointCode() + "_M");
+ reqDTO.setPointCode3(rawFoilPointIVTDO.getPointCode() + "_K");
+ reqDTO.setMaterialCode(rawFoilWorkOrderDO.getContainerName());
+ reqDTO.setPriority("1");
+ reqDTO.setProductArea(rawFoilWorkOrderDO.getProductionArea());
+ reqDTO.setIsAutoIssue("1");
+ reqDTO.setIsCreateFinish(true);
+ reqDTO.setTaskType(TaskTypeEnum.RAW_FOIL_STANDARD_TASK.getCode());
+
+ // 分配母卷下料位并占用、创建搬运任务;失败时补偿释放已占用的点位,避免点位死锁
+ RawFoilCashePositionDO unloadingPosition = null;
+ try {
+ // 分配母卷下料位并占用(优先级:称重位 > 称重缓存位 > 常规缓存位)
+ unloadingPosition = rawFoilCashePositionService.allocateUnloadingPosition();
+ reqDTO.setPointCode4(unloadingPosition.getPointCode());
+
+ CommonResult result = transportTaskApi.createTransportTask(reqDTO);
+ if (result.isError()) {
+ log.error("创建搬运任务失败, workorderId={}, reqDTO={}, 返回={}",
+ needEmptyAxisReqVO.getWorkorderId(), reqDTO, result);
+ throw exception(RAW_FOIL_TRANSPORT_TASK_CREATE_FAIL);
+ }
+ } catch (Exception e) {
+ // 补偿释放:生箔机点位 + 母卷下料位(下料位尚未分配成功时跳过)
+ rawFoilPointIVTService.releasePointLock(rawFoilPointIVTDO.getPointCode());
+ if (ObjectUtil.isNotEmpty(unloadingPosition)) {
+ rawFoilCashePositionService.releasePositionLock(unloadingPosition.getPointCode());
+ }
+ throw e;
+ }
+
+ // 更新生箔工单状态
+ rawFoilWorkOrderDO.setStatus(RawFoilWorkOrderStatusEnum.EXECUTION.getCode());
+ rawFoilWorkOrderMapper.updateById(rawFoilWorkOrderDO);
+ }
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilcasheposition/RawFoilCashePositionService.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilcasheposition/RawFoilCashePositionService.java
new file mode 100644
index 00000000..e738ade5
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilcasheposition/RawFoilCashePositionService.java
@@ -0,0 +1,104 @@
+package cn.code.nl.module.lms.service.rawfoilcasheposition;
+
+import java.util.*;
+import jakarta.validation.*;
+import cn.code.nl.module.lms.controller.admin.rawfoilcasheposition.vo.*;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilcasheposition.RawFoilCashePositionDO;
+import cn.code.nl.framework.common.pojo.PageResult;
+import cn.code.nl.framework.common.pojo.PageParam;
+
+/**
+ * 生箔母卷缓存位 Service 接口
+ *
+ * @author 诺力管理员
+ */
+public interface RawFoilCashePositionService {
+
+ /**
+ * 创建生箔母卷缓存位
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createRawFoilCashePosition(@Valid RawFoilCashePositionSaveReqVO createReqVO);
+
+ /**
+ * 更新生箔母卷缓存位
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateRawFoilCashePosition(@Valid RawFoilCashePositionSaveReqVO updateReqVO);
+
+ /**
+ * 删除生箔母卷缓存位
+ *
+ * @param id 编号
+ */
+ void deleteRawFoilCashePosition(Long id);
+
+ /**
+ * 批量删除生箔母卷缓存位
+ *
+ * @param ids 编号
+ */
+ void deleteRawFoilCashePositionListByIds(List ids);
+
+ /**
+ * 获得生箔母卷缓存位
+ *
+ * @param id 编号
+ * @return 生箔母卷缓存位
+ */
+ RawFoilCashePositionDO getRawFoilCashePosition(Long id);
+
+ /**
+ * 获得生箔母卷缓存位分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 生箔母卷缓存位分页
+ */
+ PageResult getRawFoilCashePositionPage(RawFoilCashePositionPageReqVO pageReqVO);
+
+ /**
+ * 分配母卷下料位并占用
+ * 优先级:称重位 > 称重缓存位 > 常规缓存位(顺序号越小离称重位越近)
+ * 通过 lock_status 条件更新原子占用,并发时同一点位只有一个调用方能抢到
+ *
+ * @return 已占用的下料位
+ */
+ RawFoilCashePositionDO allocateUnloadingPosition();
+
+ /**
+ * 母卷到达下料位:写入母卷信息并释放占用(任务完成回调用)
+ *
+ * @param pointCode 下料位编码
+ * @param containerName 母卷号
+ * @param workorderId 母卷工单标识(可为空,反查工单失败时传 null)
+ */
+ void handlePositionInstorage(String pointCode, String containerName, String workorderId);
+
+ /**
+ * 释放下料位占用(任务取消、任务创建失败补偿用)
+ *
+ * @param pointCode 下料位编码
+ */
+ void releasePositionLock(String pointCode);
+
+ /**
+ * 分配常规缓存位并占用
+ * 无优先级排序需求:任一空闲常规位即可,通过 lock_status 条件更新原子占用
+ *
+ * @return 已占用的常规缓存位
+ */
+ RawFoilCashePositionDO allocateConventionalPosition();
+
+ /**
+ * 母卷离开起点:清空起点点位(称重位)上的母卷记录(任务完成回调用)
+ * 仅当点位上的母卷号匹配时清空,重复回调幂等
+ *
+ * @param pointCode 起点点位编码
+ * @param containerName 母卷号
+ */
+ void handlePositionOutstock(String pointCode, String containerName);
+
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilcasheposition/RawFoilCashePositionServiceImpl.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilcasheposition/RawFoilCashePositionServiceImpl.java
new file mode 100644
index 00000000..35e21cfb
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilcasheposition/RawFoilCashePositionServiceImpl.java
@@ -0,0 +1,152 @@
+package cn.code.nl.module.lms.service.rawfoilcasheposition;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.IdUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import jakarta.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.*;
+import cn.code.nl.module.lms.controller.admin.rawfoilcasheposition.vo.*;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilcasheposition.RawFoilCashePositionDO;
+import cn.code.nl.module.lms.enums.RawFoilCashePositionTypeEnum;
+import cn.code.nl.framework.common.pojo.PageResult;
+import cn.code.nl.framework.common.pojo.PageParam;
+import cn.code.nl.framework.common.util.object.BeanUtils;
+
+import cn.code.nl.module.lms.dal.mysql.rawfoilcasheposition.RawFoilCashePositionMapper;
+
+import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.code.nl.framework.common.util.collection.CollectionUtils.convertList;
+import static cn.code.nl.framework.common.util.collection.CollectionUtils.diffList;
+import static cn.code.nl.module.lms.enums.ErrorCodeConstants.*;
+
+/**
+ * 生箔母卷缓存位 Service 实现类
+ *
+ * @author 诺力管理员
+ */
+@Slf4j
+@Service
+@Validated
+public class RawFoilCashePositionServiceImpl implements RawFoilCashePositionService {
+
+ /** 母卷下料位分配优先级:称重位 > 称重缓存位 > 常规缓存位 */
+ private static final List UNLOADING_POSITION_PRIORITY = List.of(
+ RawFoilCashePositionTypeEnum.WEIGHING_POSITION.getCode(),
+ RawFoilCashePositionTypeEnum.WEIGHING_BUFFER_POSITION.getCode(),
+ RawFoilCashePositionTypeEnum.CONVENTIONAL.getCode());
+
+ @Resource
+ private RawFoilCashePositionMapper rawFoilCashePositionMapper;
+
+ @Override
+ public Long createRawFoilCashePosition(RawFoilCashePositionSaveReqVO createReqVO) {
+ // 插入
+ RawFoilCashePositionDO rawFoilCashePosition = BeanUtils.toBean(createReqVO, RawFoilCashePositionDO.class);
+ rawFoilCashePosition.setIvtId(IdUtil.getSnowflakeNextId());
+ rawFoilCashePositionMapper.insert(rawFoilCashePosition);
+
+ // 返回
+ return rawFoilCashePosition.getIvtId();
+ }
+
+ @Override
+ public void updateRawFoilCashePosition(RawFoilCashePositionSaveReqVO updateReqVO) {
+ // 校验存在
+ validateRawFoilCashePositionExists(updateReqVO.getIvtId());
+ // 更新
+ RawFoilCashePositionDO updateObj = BeanUtils.toBean(updateReqVO, RawFoilCashePositionDO.class);
+ rawFoilCashePositionMapper.updateById(updateObj);
+ }
+
+ @Override
+ public void deleteRawFoilCashePosition(Long id) {
+ // 校验存在
+ validateRawFoilCashePositionExists(id);
+ // 删除
+ rawFoilCashePositionMapper.deleteById(id);
+ }
+
+ @Override
+ public void deleteRawFoilCashePositionListByIds(List ids) {
+ // 删除
+ rawFoilCashePositionMapper.deleteByIds(ids);
+ }
+
+
+ private void validateRawFoilCashePositionExists(Long id) {
+ if (rawFoilCashePositionMapper.selectById(id) == null) {
+ throw exception(RAW_FOIL_CASHE_POSITION_NOT_EXISTS);
+ }
+ }
+
+ @Override
+ public RawFoilCashePositionDO getRawFoilCashePosition(Long id) {
+ return rawFoilCashePositionMapper.selectById(id);
+ }
+
+ @Override
+ public PageResult getRawFoilCashePositionPage(RawFoilCashePositionPageReqVO pageReqVO) {
+ return rawFoilCashePositionMapper.selectPage(pageReqVO);
+ }
+
+ @Override
+ public RawFoilCashePositionDO allocateUnloadingPosition() {
+ return allocatePositionByPriority(UNLOADING_POSITION_PRIORITY);
+ }
+
+ @Override
+ public RawFoilCashePositionDO allocateConventionalPosition() {
+ // 常规缓存位无优先级排序需求,单类型直接分配
+ return allocatePositionByPriority(List.of(RawFoilCashePositionTypeEnum.CONVENTIONAL.getCode()));
+ }
+
+ /**
+ * 按点位类型优先级顺序分配点位并占用
+ * 逐级查询某类型全部空闲候选位,逐个尝试 CAS 占用;抢占失败(已被并发请求抢走)则顺延下一个候选位
+ *
+ * @param pointTypes 点位类型编码优先级列表
+ * @return 已占用的点位
+ */
+ private RawFoilCashePositionDO allocatePositionByPriority(List pointTypes) {
+ for (String pointType : pointTypes) {
+ List candidates = rawFoilCashePositionMapper.selectEmptyPositionList(pointType);
+ for (RawFoilCashePositionDO candidate : candidates) {
+ if (rawFoilCashePositionMapper.lockPosition(candidate.getIvtId()) > 0) {
+ return candidate;
+ }
+ }
+ }
+ throw exception(RAW_FOIL_CASHE_POSITION_NOT_SELECT);
+ }
+
+ @Override
+ public void handlePositionInstorage(String pointCode, String containerName, String workorderId) {
+ int rows = rawFoilCashePositionMapper.instoragePosition(pointCode, containerName,
+ workorderId, LocalDateTime.now());
+ if (rows == 0) {
+ log.info("下料位入库跳过(点位未被占用或已入库), pointCode={}, containerName={}", pointCode, containerName);
+ }
+ }
+
+ @Override
+ public void releasePositionLock(String pointCode) {
+ int rows = rawFoilCashePositionMapper.releaseLockByPointCode(pointCode);
+ if (rows == 0) {
+ log.info("下料位占用释放跳过(点位未被占用), pointCode={}", pointCode);
+ }
+ }
+
+ @Override
+ public void handlePositionOutstock(String pointCode, String containerName) {
+ int rows = rawFoilCashePositionMapper.outstockPosition(pointCode, containerName);
+ if (rows == 0) {
+ log.info("起点母卷出库跳过(点位上无该母卷), pointCode={}, containerName={}", pointCode, containerName);
+ }
+ }
+
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilemptyrollercasheposition/RawFoilEmptyRollerCashePositionService.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilemptyrollercasheposition/RawFoilEmptyRollerCashePositionService.java
new file mode 100644
index 00000000..1877e222
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilemptyrollercasheposition/RawFoilEmptyRollerCashePositionService.java
@@ -0,0 +1,73 @@
+package cn.code.nl.module.lms.service.rawfoilemptyrollercasheposition;
+
+import java.util.*;
+
+import cn.code.nl.module.lms.dal.dataobject.rawfoilcasheposition.RawFoilCashePositionDO;
+import jakarta.validation.*;
+import cn.code.nl.module.lms.controller.admin.rawfoilemptyrollercasheposition.vo.*;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilemptyrollercasheposition.RawFoilEmptyRollerCashePositionDO;
+import cn.code.nl.framework.common.pojo.PageResult;
+import cn.code.nl.framework.common.pojo.PageParam;
+
+/**
+ * 空辊缓存位 Service 接口
+ *
+ * @author 诺力管理员
+ */
+public interface RawFoilEmptyRollerCashePositionService {
+
+ /**
+ * 创建空辊缓存位
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createRawFoilEmptyRollerCashePosition(@Valid RawFoilEmptyRollerCashePositionSaveReqVO createReqVO);
+
+ /**
+ * 更新空辊缓存位
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateRawFoilEmptyRollerCashePosition(@Valid RawFoilEmptyRollerCashePositionSaveReqVO updateReqVO);
+
+ /**
+ * 删除空辊缓存位
+ *
+ * @param id 编号
+ */
+ void deleteRawFoilEmptyRollerCashePosition(Long id);
+
+ /**
+ * 批量删除空辊缓存位
+ *
+ * @param ids 编号
+ */
+ void deleteRawFoilEmptyRollerCashePositionListByIds(List ids);
+
+ /**
+ * 获得空辊缓存位
+ *
+ * @param id 编号
+ * @return 空辊缓存位
+ */
+ RawFoilEmptyRollerCashePositionDO getRawFoilEmptyRollerCashePosition(Long id);
+
+ /**
+ * 获得空辊缓存位分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 空辊缓存位分页
+ */
+ PageResult getRawFoilEmptyRollerCashePositionPage(RawFoilEmptyRollerCashePositionPageReqVO pageReqVO);
+
+ /**
+ * 分配空辊位并占用
+ * 按照顺序分配
+ * 通过 lock_status 条件更新原子占用,并发时同一点位只有一个调用方能抢到
+ *
+ * @return 已占用的空辊位
+ */
+ RawFoilEmptyRollerCashePositionDO allocateLoadingPosition(String pointType);
+
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilemptyrollercasheposition/RawFoilEmptyRollerCashePositionServiceImpl.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilemptyrollercasheposition/RawFoilEmptyRollerCashePositionServiceImpl.java
new file mode 100644
index 00000000..c7f2864c
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilemptyrollercasheposition/RawFoilEmptyRollerCashePositionServiceImpl.java
@@ -0,0 +1,105 @@
+package cn.code.nl.module.lms.service.rawfoilemptyrollercasheposition;
+
+import cn.code.nl.module.lms.dal.dataobject.rawfoilcasheposition.RawFoilCashePositionDO;
+import cn.code.nl.module.lms.enums.StockStatusEnum;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.ObjectUtil;
+import org.springframework.stereotype.Service;
+import jakarta.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.*;
+import cn.code.nl.module.lms.controller.admin.rawfoilemptyrollercasheposition.vo.*;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilemptyrollercasheposition.RawFoilEmptyRollerCashePositionDO;
+import cn.code.nl.framework.common.pojo.PageResult;
+import cn.code.nl.framework.common.pojo.PageParam;
+import cn.code.nl.framework.common.util.object.BeanUtils;
+
+import cn.code.nl.module.lms.dal.mysql.rawfoilemptyrollercasheposition.RawFoilEmptyRollerCashePositionMapper;
+
+import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.code.nl.framework.common.util.collection.CollectionUtils.convertList;
+import static cn.code.nl.framework.common.util.collection.CollectionUtils.diffList;
+import static cn.code.nl.module.lms.enums.ErrorCodeConstants.*;
+
+/**
+ * 空辊缓存位 Service 实现类
+ *
+ * @author 诺力管理员
+ */
+@Service
+@Validated
+public class RawFoilEmptyRollerCashePositionServiceImpl implements RawFoilEmptyRollerCashePositionService {
+
+ @Resource
+ private RawFoilEmptyRollerCashePositionMapper rawFoilEmptyRollerCashePositionMapper;
+
+ @Override
+ public Long createRawFoilEmptyRollerCashePosition(RawFoilEmptyRollerCashePositionSaveReqVO createReqVO) {
+ // 插入
+ RawFoilEmptyRollerCashePositionDO rawFoilEmptyRollerCashePosition = BeanUtils.toBean(createReqVO, RawFoilEmptyRollerCashePositionDO.class);
+
+ rawFoilEmptyRollerCashePosition.setPointId(IdUtil.getSnowflakeNextId());
+ rawFoilEmptyRollerCashePositionMapper.insert(rawFoilEmptyRollerCashePosition);
+
+ // 返回
+ return rawFoilEmptyRollerCashePosition.getPointId();
+ }
+
+ @Override
+ public void updateRawFoilEmptyRollerCashePosition(RawFoilEmptyRollerCashePositionSaveReqVO updateReqVO) {
+ // 校验存在
+ validateRawFoilEmptyRollerCashePositionExists(updateReqVO.getPointId());
+ // 更新
+ RawFoilEmptyRollerCashePositionDO updateObj = BeanUtils.toBean(updateReqVO, RawFoilEmptyRollerCashePositionDO.class);
+ rawFoilEmptyRollerCashePositionMapper.updateById(updateObj);
+ }
+
+ @Override
+ public void deleteRawFoilEmptyRollerCashePosition(Long id) {
+ // 校验存在
+ validateRawFoilEmptyRollerCashePositionExists(id);
+ // 删除
+ rawFoilEmptyRollerCashePositionMapper.deleteById(id);
+ }
+
+ @Override
+ public void deleteRawFoilEmptyRollerCashePositionListByIds(List ids) {
+ // 删除
+ rawFoilEmptyRollerCashePositionMapper.deleteByIds(ids);
+ }
+
+
+ private void validateRawFoilEmptyRollerCashePositionExists(Long id) {
+ if (rawFoilEmptyRollerCashePositionMapper.selectById(id) == null) {
+ throw exception(RAW_FOIL_EMPTY_ROLLER_CASHE_POSITION_NOT_EXISTS);
+ }
+ }
+
+ @Override
+ public RawFoilEmptyRollerCashePositionDO getRawFoilEmptyRollerCashePosition(Long id) {
+ return rawFoilEmptyRollerCashePositionMapper.selectById(id);
+ }
+
+ @Override
+ public PageResult getRawFoilEmptyRollerCashePositionPage(RawFoilEmptyRollerCashePositionPageReqVO pageReqVO) {
+ return rawFoilEmptyRollerCashePositionMapper.selectPage(pageReqVO);
+ }
+
+ @Override
+ public RawFoilEmptyRollerCashePositionDO allocateLoadingPosition(String pointType) {
+
+ List candidates = rawFoilEmptyRollerCashePositionMapper.selectEmptyPositionList(pointType, StockStatusEnum.YES.getCode());
+ // 尝试 CAS 占用
+ for (RawFoilEmptyRollerCashePositionDO candidate : candidates) {
+ if (rawFoilEmptyRollerCashePositionMapper.lockPosition(candidate.getPointId()) > 0) {
+ return candidate;
+ }
+ }
+ throw exception(EMPTY_ROLLER_CASHE_POSITION_NOT_ALLOCATE);
+ }
+
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilpointivt/RawFoilPointIVTService.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilpointivt/RawFoilPointIVTService.java
index 44734659..d97e8084 100644
--- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilpointivt/RawFoilPointIVTService.java
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilpointivt/RawFoilPointIVTService.java
@@ -1,62 +1,78 @@
-package cn.code.nl.module.lms.service.rawfoilpointivt;
-
-import java.util.*;
-import jakarta.validation.*;
-import cn.code.nl.module.lms.controller.admin.rawfoilpointivt.vo.*;
-import cn.code.nl.module.lms.dal.dataobject.rawfoilpointivt.RawFoilPointIVTDO;
-import cn.code.nl.framework.common.pojo.PageResult;
-import cn.code.nl.framework.common.pojo.PageParam;
-
-/**
- * 生箔点位库存 Service 接口
- *
- * @author 诺力管理员
- */
-public interface RawFoilPointIVTService {
-
- /**
- * 创建生箔点位库存
- *
- * @param createReqVO 创建信息
- * @return 编号
- */
- Long createRawFoilPointIVT(@Valid RawFoilPointIVTSaveReqVO createReqVO);
-
- /**
- * 更新生箔点位库存
- *
- * @param updateReqVO 更新信息
- */
- void updateRawFoilPointIVT(@Valid RawFoilPointIVTSaveReqVO updateReqVO);
-
- /**
- * 删除生箔点位库存
- *
- * @param id 编号
- */
- void deleteRawFoilPointIVT(Long id);
-
- /**
- * 批量删除生箔点位库存
- *
- * @param ids 编号
- */
- void deleteRawFoilPointIVTListByIds(List ids);
-
- /**
- * 获得生箔点位库存
- *
- * @param id 编号
- * @return 生箔点位库存
- */
- RawFoilPointIVTDO getRawFoilPointIVT(Long id);
-
- /**
- * 获得生箔点位库存分页
- *
- * @param pageReqVO 分页查询
- * @return 生箔点位库存分页
- */
- PageResult getRawFoilPointIVTPage(RawFoilPointIVTPageReqVO pageReqVO);
-
-}
\ No newline at end of file
+package cn.code.nl.module.lms.service.rawfoilpointivt;
+
+import java.util.*;
+import jakarta.validation.*;
+import cn.code.nl.module.lms.controller.admin.rawfoilpointivt.vo.*;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilpointivt.RawFoilPointIVTDO;
+import cn.code.nl.framework.common.pojo.PageResult;
+import cn.code.nl.framework.common.pojo.PageParam;
+
+/**
+ * 生箔点位库存 Service 接口
+ *
+ * @author 诺力管理员
+ */
+public interface RawFoilPointIVTService {
+
+ /**
+ * 创建生箔点位库存
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createRawFoilPointIVT(@Valid RawFoilPointIVTSaveReqVO createReqVO);
+
+ /**
+ * 更新生箔点位库存
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateRawFoilPointIVT(@Valid RawFoilPointIVTSaveReqVO updateReqVO);
+
+ /**
+ * 删除生箔点位库存
+ *
+ * @param id 编号
+ */
+ void deleteRawFoilPointIVT(Long id);
+
+ /**
+ * 批量删除生箔点位库存
+ *
+ * @param ids 编号
+ */
+ void deleteRawFoilPointIVTListByIds(List ids);
+
+ /**
+ * 获得生箔点位库存
+ *
+ * @param id 编号
+ * @return 生箔点位库存
+ */
+ RawFoilPointIVTDO getRawFoilPointIVT(Long id);
+
+ /**
+ * 获得生箔点位库存分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 生箔点位库存分页
+ */
+ PageResult getRawFoilPointIVTPage(RawFoilPointIVTPageReqVO pageReqVO);
+
+ /**
+ * 分配并占用生箔机点位:校验点位存在、已启用后 CAS 占用
+ * 点位不存在、未启用、抢占失败时抛出对应业务异常
+ *
+ * @param pointCode 点位编码
+ * @return 已占用的生箔机点位信息
+ */
+ RawFoilPointIVTDO allocatePoint(String pointCode);
+
+ /**
+ * 释放生箔机点位占用:幂等释放,仅当点位被占用时释放
+ *
+ * @param pointCode 点位编码
+ */
+ void releasePointLock(String pointCode);
+
+}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilpointivt/RawFoilPointIVTServiceImpl.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilpointivt/RawFoilPointIVTServiceImpl.java
index cacb287e..51e796a9 100644
--- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilpointivt/RawFoilPointIVTServiceImpl.java
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilpointivt/RawFoilPointIVTServiceImpl.java
@@ -1,7 +1,10 @@
package cn.code.nl.module.lms.service.rawfoilpointivt;
+import cn.code.nl.framework.common.enums.CommonStatusEnum;
import cn.code.nl.framework.security.core.util.SecurityFrameworkUtils;
import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
@@ -26,6 +29,7 @@ import static cn.code.nl.module.lms.enums.ErrorCodeConstants.*;
*
* @author 诺力管理员
*/
+@Slf4j
@Service
@Validated
public class RawFoilPointIVTServiceImpl implements RawFoilPointIVTService {
@@ -83,4 +87,30 @@ public class RawFoilPointIVTServiceImpl implements RawFoilPointIVTService {
return rawFoilPointIVTMapper.selectPage(pageReqVO);
}
+ @Override
+ public RawFoilPointIVTDO allocatePoint(String pointCode) {
+ // 校验生箔机点位是否存在
+ RawFoilPointIVTDO rawFoilPointIVT = rawFoilPointIVTMapper.selectByPointCode(pointCode);
+ if (ObjectUtil.isEmpty(rawFoilPointIVT)) {
+ throw exception(RAW_FOIL_WORK_ORDER_POINT_CODE_NOT_EXISTS);
+ }
+ // 校验生箔机点位是否启用
+ if (String.valueOf(CommonStatusEnum.ENABLE.getStatus()).equals(rawFoilPointIVT.getIsUsed())) {
+ throw exception(RAW_FOIL_WORK_ORDER_POINT_CODE_NOT_USED);
+ }
+ // CAS 占用:抢占失败说明已被其他工单占用
+ if (rawFoilPointIVTMapper.lockPoint(rawFoilPointIVT.getPointId()) == 0) {
+ throw exception(RAW_FOIL_WORK_ORDER_POINT_OCCUPIED, rawFoilPointIVT.getPointCode());
+ }
+ return rawFoilPointIVT;
+ }
+
+ @Override
+ public void releasePointLock(String pointCode) {
+ int rows = rawFoilPointIVTMapper.releaseLockByPointCode(pointCode);
+ if (rows == 0) {
+ log.info("生箔机点位占用释放跳过(点位未被占用), pointCode={}", pointCode);
+ }
+ }
+
}
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilworkorder/RawFoilWorkOrderServiceImpl.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilworkorder/RawFoilWorkOrderServiceImpl.java
index 9d7363e2..a144917f 100644
--- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilworkorder/RawFoilWorkOrderServiceImpl.java
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/rawfoilworkorder/RawFoilWorkOrderServiceImpl.java
@@ -7,6 +7,9 @@ import cn.code.nl.module.base.api.materialbase.dto.MaterialBaseRespDTO;
import cn.code.nl.module.lms.dal.dataobject.rawfoilpointivt.RawFoilPointIVTDO;
import cn.code.nl.module.lms.dal.mysql.rawfoilpointivt.RawFoilPointIVTMapper;
import cn.code.nl.module.lms.enums.RawFoilWorkOrderStatusEnum;
+import cn.code.nl.module.task.api.TransportTaskApi;
+import cn.code.nl.module.task.dto.TaskInfoDTO;
+import cn.code.nl.module.task.enums.TaskOwnerServiceEnum;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import org.springframework.stereotype.Service;
@@ -48,6 +51,9 @@ public class RawFoilWorkOrderServiceImpl implements RawFoilWorkOrderService {
@Resource
private MaterialBaseApi materialBaseApi;
+ @Resource
+ private TransportTaskApi transportTaskApi;
+
@Override
public Long createRawFoilWorkOrder(RawFoilWorkOrderSaveReqVO createReqVO) {
@@ -176,7 +182,14 @@ public class RawFoilWorkOrderServiceImpl implements RawFoilWorkOrderService {
throw exception(RAW_FOIL_WORK_ORDER_ALREADY_ENDED);
}
- // TODO 校验该生箔工单存在未完成的任务,请先完成任务。
+ // 校验该生箔工单存在未完成的任务,请先完成任务。
+ CommonResult> result = transportTaskApi.getRunningTaskByMaterialCode(workOrder.getContainerName(), TaskOwnerServiceEnum.LMS.getCode());
+ if (result.isError()){
+ throw exception(RAW_FOIL_WORK_ORDER_FAIL);
+ }
+ if (result.getData() != null){
+ throw exception(RAW_FOIL_WORK_ORDER_NOT_SELECT);
+ }
// 更新为结束状态,并记录结束时间
RawFoilWorkOrderDO updateObj = new RawFoilWorkOrderDO();
diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/task/RawFoilTask.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/task/RawFoilTask.java
new file mode 100644
index 00000000..a51ffd54
--- /dev/null
+++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/task/RawFoilTask.java
@@ -0,0 +1,115 @@
+package cn.code.nl.module.lms.task;
+
+import cn.code.nl.framework.common.pojo.CommonResult;
+import cn.code.nl.framework.execute.core.AbstractTask;
+import cn.code.nl.framework.execute.core.dto.TaskExecuteDTO;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilemptyrollercasheposition.RawFoilEmptyRollerCashePositionDO;
+import cn.code.nl.module.lms.dal.dataobject.rawfoilworkorder.RawFoilWorkOrderDO;
+import cn.code.nl.module.lms.dal.mysql.rawfoilemptyrollercasheposition.RawFoilEmptyRollerCashePositionMapper;
+import cn.code.nl.module.lms.dal.mysql.rawfoilworkorder.RawFoilWorkOrderMapper;
+import cn.code.nl.module.lms.enums.EmptyRollerPointTypeEnum;
+import cn.code.nl.module.lms.enums.RawFoilHandleCodeConstants;
+import cn.code.nl.module.lms.service.rawfoilcasheposition.RawFoilCashePositionService;
+import cn.code.nl.module.lms.service.rawfoilemptyrollercasheposition.RawFoilEmptyRollerCashePositionService;
+import cn.code.nl.module.task.api.TransportTaskApi;
+import cn.code.nl.module.task.dto.TaskInfoDTO;
+import cn.code.nl.module.task.enums.TransportTaskStatusEnum;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.code.nl.module.lms.enums.ErrorCodeConstants.RAW_FOIL_TASK_ERROR;
+
+/**
+ * 生箔搬运任务回调处理器
+ * 任务完成:母卷到达下料位,写入母卷信息并释放点位占用
+ * 任务取消:释放下料位占用
+ *
+ * @author dsh
+ * 2026/7/28
+ */
+@Slf4j
+@Component(RawFoilHandleCodeConstants.RAW_FOIL_TASK)
+public class RawFoilTask extends AbstractTask {
+
+ @Resource
+ private TransportTaskApi transportTaskApi;
+
+ @Resource
+ private RawFoilCashePositionService rawFoilCashePositionService;
+
+ @Resource
+ private RawFoilEmptyRollerCashePositionService rawFoilEmptyRollerCashePositionService;
+
+ @Resource
+ private RawFoilWorkOrderMapper rawFoilWorkOrderMapper;
+
+ /**
+ * 处理任务完成:母卷到达下料位,写入母卷信息并释放点位占用
+ *
+ * @param taskExecuteDTO 任务执行信息
+ */
+ @Override
+ public void doHandleFinish(TaskExecuteDTO taskExecuteDTO) {
+ // 查询任务全量信息,获取下料位编码和母卷号
+ TaskInfoDTO task = getTaskInfo(taskExecuteDTO.getTaskId());
+ if (task == null) {
+ return;
+ }
+ // 用母卷号反查未结束工单,获取工单标识(反查失败仅告警,不阻塞入库主流程)
+ RawFoilWorkOrderDO workOrder = rawFoilWorkOrderMapper
+ .selectByContainerNameAndNotEndStatus(task.getMaterialCode());
+ if (workOrder == null) {
+ log.warn("母卷号反查工单失败, containerName={}, taskId={}",
+ task.getMaterialCode(), task.getTaskId());
+ }
+ String workorderId = workOrder != null ? String.valueOf(workOrder.getWorkorderId()) : null;
+ // 母卷到达下料位:写入母卷信息并释放占用
+ rawFoilCashePositionService.handlePositionInstorage(
+ task.getPointCode4(), task.getMaterialCode(), workorderId);
+
+
+ }
+
+ /**
+ * 处理任务取消:释放下料位占用
+ *
+ * @param taskExecuteDTO 任务执行信息
+ */
+ @Override
+ public void doHandleCancel(TaskExecuteDTO taskExecuteDTO) {
+ TaskInfoDTO task = getTaskInfo(taskExecuteDTO.getTaskId());
+ if (task == null) {
+ return;
+ }
+ rawFoilCashePositionService.releasePositionLock(task.getPointCode4());
+ }
+
+ @Override
+ public String againApply(TaskExecuteDTO taskExecuteDTO) {
+ TaskInfoDTO task = getTaskInfo(taskExecuteDTO.getTaskId());
+ if (task == null){
+ throw exception(RAW_FOIL_TASK_ERROR);
+ }
+ //二次分配库位 分配生箔空辊点
+ RawFoilEmptyRollerCashePositionDO rawFoilEmptyRollerCashePositionDO = rawFoilEmptyRollerCashePositionService.allocateLoadingPosition(EmptyRollerPointTypeEnum.RAW_FOIL_EMPTY_ROLLER_POINT.getCode());
+ return rawFoilEmptyRollerCashePositionDO.getPointCode();
+ }
+
+ /**
+ * 查询任务信息,查询失败或任务不存在或任务状态为最终状态时记录告警并返回 null(不抛异常,避免 MQ 无限重试)
+ *
+ * @param taskId 任务标识
+ * @return 任务信息,不存在时返回 null
+ */
+ private TaskInfoDTO getTaskInfo(Long taskId) {
+ CommonResult result = transportTaskApi.getTaskById(taskId);
+ if (result.isError() || result.getData() == null) {
+ log.warn("任务不存在或查询失败,跳过点位状态处理, taskId={}, 返回={}", taskId, result);
+ return null;
+ }
+ return result.getData();
+ }
+
+}
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
index cb823736..836b81dd 100644
--- 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
@@ -3,9 +3,14 @@
rocketmq:
name-server: 192.168.81.193:9876
producer:
- group: lms_producer_dev_group # 事务消息需要配置一样
+ group: nl_producer_dev_group
send-message-timeout: 3000
consumer:
+ wms-task-operate:
+ group: wms_task_status_change_dev_group
+ topic: wms_task_status_change_dev_topic
lms-task-operate:
group: lms_task_status_change_dev_group
- topic: lms_task_status_change_dev_topic
\ No newline at end of file
+ topic: lms_task_status_change_dev_topic
+ task:
+ topic: task_status_change_dev_topic
\ No newline at end of file
diff --git a/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/enums/AcsTaskTypeEnum.java b/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/enums/AcsTaskTypeEnum.java
new file mode 100644
index 00000000..6b80c9ba
--- /dev/null
+++ b/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/enums/AcsTaskTypeEnum.java
@@ -0,0 +1,24 @@
+package cn.code.nl.module.task.enums;
+
+import lombok.Getter;
+
+/**
+ * @author dsh
+ * 2026/7/28
+ */
+@Getter
+public enum AcsTaskTypeEnum {
+
+ AGV_TASK("1","agv任务"),
+ TRUSS_TASK("6","桁架任务");
+
+
+ private String code;
+
+ private String name;
+
+ AcsTaskTypeEnum(String code,String name){
+ this.code = code;
+ this.name = name;
+ }
+}
diff --git a/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/enums/TaskOwnerServiceEnum.java b/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/enums/TaskOwnerServiceEnum.java
new file mode 100644
index 00000000..58485d0a
--- /dev/null
+++ b/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/enums/TaskOwnerServiceEnum.java
@@ -0,0 +1,23 @@
+package cn.code.nl.module.task.enums;
+
+import lombok.Getter;
+
+/**
+ * @author dsh
+ * 2026/7/29
+ */
+@Getter
+public enum TaskOwnerServiceEnum {
+
+ LMS("LMS","生产业务"),
+ WMS("WMS","仓储业务");
+
+ private String code;
+
+ private String name;
+
+ TaskOwnerServiceEnum(String code,String name){
+ this.code = code;
+ this.name = name;
+ }
+}
diff --git a/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/enums/TaskTypeEnum.java b/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/enums/TaskTypeEnum.java
new file mode 100644
index 00000000..b861612a
--- /dev/null
+++ b/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/enums/TaskTypeEnum.java
@@ -0,0 +1,24 @@
+package cn.code.nl.module.task.enums;
+
+import lombok.Getter;
+
+/**
+ * @author dsh
+ * 2026/7/30
+ */
+@Getter
+public enum TaskTypeEnum {
+
+ RAW_FOIL_STANDARD_TASK("010101","生箔标准任务"),
+ RAW_FOIL_INSTORAGE_TASK("010102","称重入库任务");
+
+
+ private String code;
+
+ private String name;
+
+ TaskTypeEnum(String code,String name){
+ this.code = code;
+ this.name = name;
+ }
+}
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 0c5c14ae..49a8aea7 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
@@ -33,7 +33,8 @@ public class TaskEventProducer {
public void publishEvent(TaskEventMessage message) {
message.setEventId(message.getTaskId().toString());
- String destination = message.getOwnerService() + "_" + topic;
+ // ownerService 为大写枚举值(LMS/WMS),topic 配置为小写前缀,RocketMQ topic 大小写敏感,需统一转小写
+ String destination = message.getOwnerService().toLowerCase() + "_" + topic;
try {
rocketMQTemplate.syncSend(destination, message);
log.info("MQ 发送成功, destination={}, taskId={}, eventType={}",
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 e1db57cf..d46659ec 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
@@ -77,7 +77,7 @@ public class TransportTaskServiceImpl implements TransportTaskService {
@Override
@LogRecord(type = TASK_INFO,
subType = TASK_INFO_OPERATE_TYPE,
- bizNo = "{{_ret}}",
+ bizNo = "{{#_ret}}",
success = TASK_INFO_CREATE_BY_RPC)
public Long createTransportTaskByRpc(TransportTaskCreateReqDTO reqDTO) {
TransportTaskDO task = BeanUtils.toBean(reqDTO, TransportTaskDO.class);
diff --git a/nl-server/src/main/resources/application-dev.yaml b/nl-server/src/main/resources/application-dev.yaml
index 4d76d57a..aea15af9 100644
--- a/nl-server/src/main/resources/application-dev.yaml
+++ b/nl-server/src/main/resources/application-dev.yaml
@@ -47,9 +47,9 @@ spring:
primary: master
datasource:
master:
- url: jdbc:mysql://192.168.10.41:3306/huachuang_lms_dev?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
+ url: jdbc:mysql://192.168.81.193:3306/huachuang_lms_dev?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
username: root
- password: root
+ password: root123
slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改
lazy: true # 开启懒加载,保证启动速度
url: jdbc:mysql://192.168.10.41:3306/huachuang_lms_dev?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
diff --git a/nl-server/src/main/resources/application.yaml b/nl-server/src/main/resources/application.yaml
index ec408e0f..158b4be7 100644
--- a/nl-server/src/main/resources/application.yaml
+++ b/nl-server/src/main/resources/application.yaml
@@ -147,11 +147,6 @@ aj:
--- #################### 消息队列相关 ####################
-# rocketmq 配置项,对应 RocketMQProperties 配置类
-rocketmq:
- # Producer 配置项
- producer:
- group: ${spring.application.name}_PRODUCER # 生产者分组
spring:
# Kafka 配置项,对应 KafkaProperties 配置类
diff --git a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/lms/rawfoilcasheposition/index.ts b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/lms/rawfoilcasheposition/index.ts
new file mode 100644
index 00000000..cf6c3ebe
--- /dev/null
+++ b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/lms/rawfoilcasheposition/index.ts
@@ -0,0 +1,67 @@
+import type { PageParam, PageResult } from '@vben/request';
+import type { Dayjs } from 'dayjs';
+
+import { requestClient } from '#/api/request';
+
+export namespace LmsRawFoilCashePositionApi {
+ /** 生箔母卷缓存位信息 */
+ export interface RawFoilCashePosition {
+ ivtId: number; // 库存记录标识
+ pointCode?: string; // 点位编码
+ containerName: string; // 母卷号
+ workorderId: string; // 母卷工单标识
+ fullVehicleCode: string; // 母卷轴编码
+ instorageTime: string | Dayjs; // 入库时间
+ productionArea: string; // 生产区域
+ pointLocation: string; // 位置
+ sortSeq?: number; // 顺序号
+ isUsed?: string; // 是否启用
+ remark: string; // 备注
+ coolIvtStatus?: string; // 库存状态
+ pointType: string; // 点位类型
+ }
+}
+
+/** 查询生箔母卷缓存位分页 */
+export function getRawFoilCashePositionPage(params: PageParam) {
+ return requestClient.get>(
+ '/lms/raw-foil-cashe-position/page',
+ { params },
+ );
+}
+
+/** 查询生箔母卷缓存位详情 */
+export function getRawFoilCashePosition(id: number) {
+ return requestClient.get(
+ `/lms/raw-foil-cashe-position/get?id=${id}`,
+ );
+}
+
+/** 新增生箔母卷缓存位 */
+export function createRawFoilCashePosition(data: LmsRawFoilCashePositionApi.RawFoilCashePosition) {
+ return requestClient.post('/lms/raw-foil-cashe-position/create', data);
+}
+
+/** 修改生箔母卷缓存位 */
+export function updateRawFoilCashePosition(data: LmsRawFoilCashePositionApi.RawFoilCashePosition) {
+ return requestClient.put('/lms/raw-foil-cashe-position/update', data);
+}
+
+/** 删除生箔母卷缓存位 */
+export function deleteRawFoilCashePosition(id: number) {
+ return requestClient.delete(`/lms/raw-foil-cashe-position/delete?id=${id}`);
+}
+
+/** 批量删除生箔母卷缓存位 */
+export function deleteRawFoilCashePositionList(ids: number[]) {
+ return requestClient.delete(
+ `/lms/raw-foil-cashe-position/delete-list?ids=${ids.join(',')}`,
+ );
+}
+
+/** 导出生箔母卷缓存位 */
+export function exportRawFoilCashePosition(params: any) {
+ return requestClient.download('/lms/raw-foil-cashe-position/export-excel', { params });
+}
+
+
diff --git a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/lms/rawfoilemptyrollercasheposition/index.ts b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/lms/rawfoilemptyrollercasheposition/index.ts
new file mode 100644
index 00000000..57844fcb
--- /dev/null
+++ b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/lms/rawfoilemptyrollercasheposition/index.ts
@@ -0,0 +1,68 @@
+import type { PageParam, PageResult } from '@vben/request';
+import type { Dayjs } from 'dayjs';
+
+import { requestClient } from '#/api/request';
+
+export namespace LmsRawFoilEmptyRollerCashePositionApi {
+ /** 空辊缓存位信息 */
+ export interface RawFoilEmptyRollerCashePosition {
+ pointId: number; // 点位标识
+ pointCode?: string; // 点位编码
+ vehicleCode: string; // 载具编码
+ productionArea: string; // 生产区域
+ pointLocation: string; // 位置
+ remark: string; // 备注
+ isUsed?: string; // 是否启用
+ creator: string; // 创建人
+ createTime?: string; // 创建时间
+ updater: string; // 修改人
+ updateTime?: string; // 修改时间
+ weight: number; // 重量
+ hasStock?: string; // 是否有货
+ sortSeq?: number; // 顺序号
+ }
+}
+
+/** 查询空辊缓存位分页 */
+export function getRawFoilEmptyRollerCashePositionPage(params: PageParam) {
+ return requestClient.get>(
+ '/lms/raw-foil-empty-roller-cashe-position/page',
+ { params },
+ );
+}
+
+/** 查询空辊缓存位详情 */
+export function getRawFoilEmptyRollerCashePosition(id: number) {
+ return requestClient.get(
+ `/lms/raw-foil-empty-roller-cashe-position/get?id=${id}`,
+ );
+}
+
+/** 新增空辊缓存位 */
+export function createRawFoilEmptyRollerCashePosition(data: LmsRawFoilEmptyRollerCashePositionApi.RawFoilEmptyRollerCashePosition) {
+ return requestClient.post('/lms/raw-foil-empty-roller-cashe-position/create', data);
+}
+
+/** 修改空辊缓存位 */
+export function updateRawFoilEmptyRollerCashePosition(data: LmsRawFoilEmptyRollerCashePositionApi.RawFoilEmptyRollerCashePosition) {
+ return requestClient.put('/lms/raw-foil-empty-roller-cashe-position/update', data);
+}
+
+/** 删除空辊缓存位 */
+export function deleteRawFoilEmptyRollerCashePosition(id: number) {
+ return requestClient.delete(`/lms/raw-foil-empty-roller-cashe-position/delete?id=${id}`);
+}
+
+/** 批量删除空辊缓存位 */
+export function deleteRawFoilEmptyRollerCashePositionList(ids: number[]) {
+ return requestClient.delete(
+ `/lms/raw-foil-empty-roller-cashe-position/delete-list?ids=${ids.join(',')}`,
+ );
+}
+
+/** 导出空辊缓存位 */
+export function exportRawFoilEmptyRollerCashePosition(params: any) {
+ return requestClient.download('/lms/raw-foil-empty-roller-cashe-position/export-excel', { params });
+}
+
+
diff --git a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/lms/rawfoilcasheposition/data.ts b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/lms/rawfoilcasheposition/data.ts
new file mode 100644
index 00000000..18880281
--- /dev/null
+++ b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/lms/rawfoilcasheposition/data.ts
@@ -0,0 +1,286 @@
+import type { VbenFormSchema } from '#/adapter/form';
+import type { VxeTableGridOptions } from '#/adapter/vxe-table';
+import type { LmsRawFoilCashePositionApi } from '#/api/lms/rawfoilcasheposition';
+
+import { getDictOptions } from '@vben/hooks';
+
+import { getRangePickerDefaultProps } from '#/utils';
+import {DICT_TYPE} from "@vben/constants";
+import {z} from "#/adapter/form";
+
+/** 新增/修改的表单 */
+export function useFormSchema(): VbenFormSchema[] {
+ return [
+ {
+ fieldName: 'ivtId',
+ component: 'Input',
+ dependencies: {
+ triggerFields: [''],
+ show: () => false,
+ },
+ },
+ {
+ fieldName: 'pointCode',
+ label: '点位编码',
+ rules: 'required',
+ component: 'Input',
+ componentProps: {
+ placeholder: '请输入点位编码',
+ },
+ },
+ {
+ fieldName: 'containerName',
+ label: '母卷号',
+ component: 'Input',
+ componentProps: {
+ placeholder: '请输入母卷号',
+ },
+ },
+ {
+ fieldName: 'workorderId',
+ label: '母卷工单标识',
+ component: 'Input',
+ componentProps: {
+ placeholder: '请输入母卷工单标识',
+ },
+ },
+ {
+ fieldName: 'fullVehicleCode',
+ label: '母卷轴编码',
+ component: 'Input',
+ componentProps: {
+ placeholder: '请输入母卷轴编码',
+ },
+ },
+ {
+ fieldName: 'instorageTime',
+ label: '入库时间',
+ component: 'DatePicker',
+ componentProps: {
+ showTime: true,
+ format: 'YYYY-MM-DD HH:mm:ss',
+ valueFormat: 'x',
+ },
+ },
+ {
+ fieldName: 'productionArea',
+ label: '生产区域',
+ component: 'Select',
+ componentProps: {
+ options: getDictOptions(DICT_TYPE.PRODUCT_AREA),
+ placeholder: '请选择生产区域',
+ },
+ },
+ {
+ fieldName: 'pointLocation',
+ label: '位置',
+ component: 'Input',
+ componentProps: {
+ placeholder: '请输入位置',
+ },
+ },
+ {
+ fieldName: 'sortSeq',
+ label: '顺序号',
+ rules: 'required',
+ component: 'Input',
+ componentProps: {
+ placeholder: '请输入顺序号',
+ },
+ },
+ {
+ fieldName: 'isUsed',
+ label: '是否启用',
+ rules: z.string().default('1'),
+ component: 'RadioGroup',
+ componentProps: {
+ options: [{ label: '是', value: '1' }, { label: '否', value: '0' }],
+ buttonStyle: 'solid',
+ optionType: 'button',
+ },
+ },
+ {
+ fieldName: 'remark',
+ label: '备注',
+ component: 'Input',
+ componentProps: {
+ placeholder: '请输入备注',
+ },
+ },
+ {
+ fieldName: 'coolIvtStatus',
+ label: '库存状态',
+ rules: 'required',
+ component: 'Select',
+ componentProps: {
+ options: getDictOptions(DICT_TYPE.RAWFOIL_CASHEPOSITION_STATUS),
+ placeholder: '请选择库存状态',
+ },
+ },
+ {
+ fieldName: 'pointType',
+ label: '点位类型',
+ component: 'Select',
+ componentProps: {
+ options: getDictOptions(DICT_TYPE.RAWFOIL_CASHEPOSITION_TYPE),
+ placeholder: '请选择点位类型',
+ },
+ },
+ ];
+}
+
+/** 列表的搜索表单 */
+export function useGridFormSchema(): VbenFormSchema[] {
+ return [
+ {
+ fieldName: 'pointCode',
+ label: '点位编码',
+ component: 'Input',
+ componentProps: {
+ allowClear: true,
+ placeholder: '请输入点位编码',
+ },
+ },
+ {
+ fieldName: 'containerName',
+ label: '母卷号',
+ component: 'Input',
+ componentProps: {
+ allowClear: true,
+ placeholder: '请输入母卷号',
+ },
+ },
+ {
+ fieldName: 'instorageTime',
+ label: '入库时间',
+ component: 'RangePicker',
+ componentProps: {
+ ...getRangePickerDefaultProps(),
+ allowClear: true,
+ },
+ },
+ {
+ fieldName: 'productionArea',
+ label: '生产区域',
+ component: 'Select',
+ componentProps: {
+ allowClear: true,
+ options: getDictOptions(DICT_TYPE.PRODUCT_AREA),
+ placeholder: '请选择生产区域',
+ },
+ },
+ {
+ fieldName: 'isUsed',
+ label: '是否启用',
+ component: 'Select',
+ componentProps: {
+ allowClear: true,
+ options: [
+ { label: '是', value: '1' },
+ { label: '否', value: '0' },
+ ],
+ placeholder: '请输入是否启用',
+ },
+ },
+ {
+ fieldName: 'coolIvtStatus',
+ label: '库存状态',
+ component: 'Select',
+ componentProps: {
+ allowClear: true,
+ options: getDictOptions(DICT_TYPE.RAWFOIL_CASHEPOSITION_STATUS),
+ placeholder: '请选择库存状态',
+ },
+ },
+ ];
+}
+
+/** 列表的字段 */
+export function useGridColumns(): VxeTableGridOptions['columns'] {
+ return [
+ { type: 'checkbox', width: 40 },
+ {
+ field: 'ivtId',
+ title: '库存记录标识',
+ minWidth: 120,
+ },
+ {
+ field: 'pointCode',
+ title: '点位编码',
+ minWidth: 120,
+ },
+ {
+ field: 'containerName',
+ title: '母卷号',
+ minWidth: 120,
+ },
+ {
+ field: 'workorderId',
+ title: '母卷工单标识',
+ minWidth: 120,
+ },
+ {
+ field: 'fullVehicleCode',
+ title: '母卷轴编码',
+ minWidth: 120,
+ },
+ {
+ field: 'instorageTime',
+ title: '入库时间',
+ minWidth: 120,
+ formatter: 'formatDateTime',
+ },
+ {
+ field: 'productionArea',
+ title: '生产区域',
+ minWidth: 120,
+ },
+ {
+ field: 'pointLocation',
+ title: '位置',
+ minWidth: 120,
+ },
+ {
+ field: 'sortSeq',
+ title: '顺序号',
+ minWidth: 120,
+ },
+ {
+ field: 'isUsed',
+ title: '是否启用',
+ minWidth: 120,
+ },
+ {
+ field: 'coolIvtStatus',
+ title: '库存状态',
+ minWidth: 120,
+ },
+ {
+ field: 'pointType',
+ title: '点位类型',
+ minWidth: 120,
+ },
+ {
+ field: 'deleted',
+ title: '是否删除',
+ minWidth: 120,
+ },
+ {
+ title: '操作',
+ width: 200,
+ fixed: 'right',
+ slots: { default: 'actions' },
+ },
+ {
+ field: 'updateTime',
+ title: '修改时间',
+ minWidth: 120,
+ },
+ {
+ field: 'remark',
+ title: '备注',
+ minWidth: 120,
+ },
+ ];
+}
+
diff --git a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/lms/rawfoilcasheposition/index.vue b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/lms/rawfoilcasheposition/index.vue
new file mode 100644
index 00000000..7f377809
--- /dev/null
+++ b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/lms/rawfoilcasheposition/index.vue
@@ -0,0 +1,186 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/lms/rawfoilcasheposition/modules/form.vue b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/lms/rawfoilcasheposition/modules/form.vue
new file mode 100644
index 00000000..b3ad3152
--- /dev/null
+++ b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/lms/rawfoilcasheposition/modules/form.vue
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
diff --git a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/lms/rawfoilemptyrollercasheposition/data.ts b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/lms/rawfoilemptyrollercasheposition/data.ts
new file mode 100644
index 00000000..a380c611
--- /dev/null
+++ b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/lms/rawfoilemptyrollercasheposition/data.ts
@@ -0,0 +1,232 @@
+import {type VbenFormSchema, z} from '#/adapter/form';
+import type { VxeTableGridOptions } from '#/adapter/vxe-table';
+import type { LmsRawFoilEmptyRollerCashePositionApi } from '#/api/lms/rawfoilemptyrollercasheposition';
+
+import { getDictOptions } from '@vben/hooks';
+
+import { getRangePickerDefaultProps } from '#/utils';
+import {DICT_TYPE} from "@vben/constants";
+
+/** 新增/修改的表单 */
+export function useFormSchema(): VbenFormSchema[] {
+ return [
+ {
+ fieldName: 'pointId',
+ component: 'Input',
+ dependencies: {
+ triggerFields: [''],
+ show: () => false,
+ },
+ },
+ {
+ fieldName: 'pointCode',
+ label: '点位编码',
+ rules: 'required',
+ component: 'Input',
+ componentProps: {
+ placeholder: '请输入点位编码',
+ },
+ },
+ {
+ fieldName: 'vehicleCode',
+ label: '载具编码',
+ component: 'Input',
+ componentProps: {
+ placeholder: '请输入载具编码',
+ },
+ },
+ {
+ fieldName: 'productionArea',
+ label: '生产区域',
+ component: 'Select',
+ componentProps: {
+ placeholder: '请输入生产区域',
+ options: getDictOptions(DICT_TYPE.PRODUCT_AREA),
+ },
+ },
+ {
+ fieldName: 'pointType',
+ label: '点位类型',
+ component: 'Select',
+ componentProps: {
+ placeholder: '请输入点位',
+ options: getDictOptions(DICT_TYPE.EMPTYROLLER_CASHEPOSITION_TYPE),
+ },
+ },
+ {
+ fieldName: 'sortSeq',
+ label: '顺序号',
+ rules: 'required',
+ component: 'Input',
+ componentProps: {
+ placeholder: '请输入顺序号',
+ },
+ },
+ {
+ fieldName: 'pointLocation',
+ label: '位置',
+ component: 'Input',
+ componentProps: {
+ placeholder: '请输入位置',
+ },
+ },
+ {
+ fieldName: 'isUsed',
+ label: '是否启用',
+ rules: z.string().default('1'),
+ component: 'RadioGroup',
+ componentProps: {
+ options: [{ label: '是', value: '1' }, { label: '否', value: '0' }],
+ buttonStyle: 'solid',
+ optionType: 'button',
+ },
+ },
+ {
+ fieldName: 'hasStock',
+ label: '是否有货',
+ rules: z.string().default('0'),
+ component: 'RadioGroup',
+ componentProps: {
+ options: [{ label: '有货', value: '1' }, { label: '无货', value: '0' }],
+ buttonStyle: 'solid',
+ optionType: 'button',
+ },
+ },
+ {
+ fieldName: 'weight',
+ label: '重量',
+ component: 'Input',
+ componentProps: {
+ placeholder: '请输入重量',
+ },
+ },
+ {
+ fieldName: 'remark',
+ label: '备注',
+ component: 'TextArea',
+ componentProps: {
+ placeholder: '请输入备注',
+ },
+ },
+ ];
+}
+
+/** 列表的搜索表单 */
+export function useGridFormSchema(): VbenFormSchema[] {
+ return [
+ {
+ fieldName: 'pointCode',
+ label: '点位编码',
+ component: 'Input',
+ componentProps: {
+ allowClear: true,
+ placeholder: '请输入点位编码',
+ },
+ },
+ {
+ fieldName: 'productionArea',
+ label: '生产区域',
+ component: 'Select',
+ componentProps: {
+ allowClear: true,
+ options: getDictOptions(DICT_TYPE.PRODUCT_AREA),
+ placeholder: '请输入生产区域',
+ },
+ },
+ {
+ fieldName: 'isUsed',
+ label: '是否启用',
+ component: 'Select',
+ componentProps: {
+ allowClear: true,
+ options: [
+ { label: '是', value: '1' },
+ { label: '否', value: '0' },
+ ],
+ placeholder: '请选择是否启用',
+ },
+ },
+ {
+ fieldName: 'hasStock',
+ label: '是否有货',
+ component: 'Select',
+ componentProps: {
+ allowClear: true,
+ options: [
+ { label: '有货', value: '1' },
+ { label: '无货', value: '0' },
+ ],
+ placeholder: '请选择是否有货',
+ },
+ },
+ ];
+}
+
+/** 列表的字段 */
+export function useGridColumns(): VxeTableGridOptions['columns'] {
+ return [
+ { type: 'checkbox', width: 40 },
+ {
+ field: 'pointId',
+ title: '点位标识',
+ minWidth: 120,
+ },
+ {
+ field: 'pointCode',
+ title: '点位编码',
+ minWidth: 120,
+ },
+ {
+ field: 'vehicleCode',
+ title: '载具编码',
+ minWidth: 120,
+ },
+ {
+ field: 'productionArea',
+ title: '生产区域',
+ minWidth: 120,
+ },
+ {
+ field: 'pointLocation',
+ title: '位置',
+ minWidth: 120,
+ },
+ {
+ field: 'remark',
+ title: '备注',
+ minWidth: 120,
+ },
+ {
+ field: 'isUsed',
+ title: '是否启用',
+ minWidth: 120,
+ },
+ {
+ field: 'updateTime',
+ title: '修改时间',
+ minWidth: 120,
+ },
+ {
+ field: 'weight',
+ title: '重量',
+ minWidth: 120,
+ },
+ {
+ field: 'hasStock',
+ title: '是否有货',
+ minWidth: 120,
+ },
+ {
+ field: 'sortSeq',
+ 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/lms/rawfoilemptyrollercasheposition/index.vue b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/lms/rawfoilemptyrollercasheposition/index.vue
new file mode 100644
index 00000000..02db5aad
--- /dev/null
+++ b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/lms/rawfoilemptyrollercasheposition/index.vue
@@ -0,0 +1,186 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/lms/rawfoilemptyrollercasheposition/modules/form.vue b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/lms/rawfoilemptyrollercasheposition/modules/form.vue
new file mode 100644
index 00000000..2fbeeb76
--- /dev/null
+++ b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/lms/rawfoilemptyrollercasheposition/modules/form.vue
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
diff --git a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/packages/constants/src/dict-enum.ts b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/packages/constants/src/dict-enum.ts
index 8b802722..8c461bf5 100644
--- a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/packages/constants/src/dict-enum.ts
+++ b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/packages/constants/src/dict-enum.ts
@@ -306,6 +306,9 @@ const TASK_DICT = {
/** ========== RawFoil - 生箔管理模块 ========== */
const RawFoil_DICT = {
RAWFOIL_WORKORDER_STATUS: 'rawfoil_workorder_status', // 生箔工序工单状态
+ RAWFOIL_CASHEPOSITION_TYPE: 'rawfoil_casheposition_type', // 生箔母卷缓存位点位类型
+ RAWFOIL_CASHEPOSITION_STATUS: 'rawfoil_casheposition_status', // 生箔母卷缓存位库存状态
+ EMPTYROLLER_CASHEPOSITION_TYPE: 'emptyroller_casheposition_type', // 空辊缓存位点位类型
} as const;
/** 字典类型枚举 - 统一导出 */