From 63f62fd7bd84493476d293a6a3b23952d980bead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9B=B9=E9=B9=8F=E9=A3=9E?= Date: Tue, 16 Jun 2026 08:02:05 +0800 Subject: [PATCH] =?UTF-8?q?feat(barcode):=20=E6=B7=BB=E5=8A=A0=E6=88=90?= =?UTF-8?q?=E6=9C=AC=E4=B8=AD=E5=BF=83=E9=80=80=E6=96=99=E6=9D=A1=E7=A0=81?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=B9=B6=E6=94=AF=E6=8C=81PDF=E5=92=8C?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在BarCodeType常量中新增CostcenterBack类型用于成本中心退料 - 实现成本中心退料物料条码PDF导出功能,支持逐个和整页两种模式 - 添加物料标签图片ZIP批量导出功能,生成PNG格式二维码标签 - 集成条码生成逻辑,自动为退料项目创建对应的二维码主数据 - 使用模板引擎生成标准化的条码打印页面布局 - 实现ZIP压缩流处理,支持多文件打包下载功能 --- .../InCostCenterBackController.java | 108 ++++++++++++++++-- .../nflg/wms/common/constant/BarCodeType.java | 6 +- 2 files changed, 102 insertions(+), 12 deletions(-) diff --git a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InCostCenterBackController.java b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InCostCenterBackController.java index acdfbb20..1004cdaa 100644 --- a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InCostCenterBackController.java +++ b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/InCostCenterBackController.java @@ -7,46 +7,47 @@ import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import com.nflg.wms.admin.pojo.dto.PdfPageDTO; import com.nflg.wms.admin.pojo.request.NoScanningItemDataRequest; -import com.nflg.wms.admin.pojo.request.NoScanningItemRequest; import com.nflg.wms.admin.pojo.request.NoScanningRequest; import com.nflg.wms.admin.repository.InMaterialScanRecordRespository; import com.nflg.wms.admin.service.BasdeSerialNumberControllerService; import com.nflg.wms.admin.service.NoScanningBaseControllerService; import com.nflg.wms.admin.service.SapService; -import com.nflg.wms.admin.util.NoUtil; -import com.nflg.wms.admin.util.PdfGeneratorUtil; -import com.nflg.wms.admin.util.QRCodeUtil; -import com.nflg.wms.admin.util.ThymeleafUtil; +import com.nflg.wms.admin.util.*; import com.nflg.wms.common.constant.BarCodeProcessStage; +import com.nflg.wms.common.constant.BarCodeType; import com.nflg.wms.common.pojo.ApiResult; import com.nflg.wms.common.pojo.PageData; import com.nflg.wms.common.pojo.document.InMaterialScanRecord; -import com.nflg.wms.common.pojo.dto.C_MaterialReturnDTO; -import com.nflg.wms.common.pojo.dto.DepartmentMaterialReturnSlipDTO; -import com.nflg.wms.common.pojo.dto.InventoryInDTO; -import com.nflg.wms.common.pojo.dto.OptRecordDTO; +import com.nflg.wms.common.pojo.dto.*; import com.nflg.wms.common.pojo.qo.*; import com.nflg.wms.common.pojo.vo.*; import com.nflg.wms.common.util.UserUtil; import com.nflg.wms.common.util.VUtil; import com.nflg.wms.repository.entity.*; import com.nflg.wms.repository.service.*; -import com.nflg.wms.starter.BaseController; -import com.nflg.wms.starter.annotation.ApiMark; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.extern.slf4j.Slf4j; +import org.springframework.core.io.ClassPathResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; +import java.io.ByteArrayOutputStream; import java.math.BigDecimal; +import java.net.URL; import java.time.Instant; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; /** * 成本中心退料相关 @@ -563,4 +564,89 @@ public class InCostCenterBackController extends BaseController { String html = ThymeleafUtil.generator("/template/", "成本中心退料单", ".html", variables); PdfGeneratorUtil.generatePdf("成本中心退料入库单" + order.getNo(), html, response); } + + /** + * 导出物料条码pdf(逐个) + * @param id 订单ID + * @param type 1:逐个,2:一页 + */ + @GetMapping("exportMaterialsPdf") + public void exportMaterials(HttpServletResponse response, @Valid @RequestParam @NotNull Long id + , @Valid @RequestParam @NotNull Integer type) throws Exception { + WmsInCostcenterBack order = inCostcenterBackService.getById(id); + VUtil.trueThrowBusinessError(Objects.isNull(order)).throwMessage("订单不存在"); + List items = inCostcenterBackItemService.lambdaQuery() + .eq(WmsInCostcenterBackItem::getOrderId, id) + .list(); + List datas = convertToPrintDTO(getQrCodesByItems(items)); + Map variables = new HashMap<>(); + variables.put("list", datas); + if (Objects.equals(type, 1)) { + String html = ThymeleafUtil.generator("/template/qrcode/", "dp-1", ".html", variables); + URL baseUrl = new ClassPathResource("template/qrcode/").getURL(); + PdfGeneratorUtil.generatePdf("普通物料条码(逐个)", html, baseUrl.toString(), response); + } else { + String html = ThymeleafUtil.generator("/template/qrcode/", "dp-2", ".html", variables); + URL baseUrl = new ClassPathResource("template/qrcode/").getURL(); + PdfGeneratorUtil.generatePdf("普通物料条码(整张)", html, baseUrl.toString(), response); + } + } + + private List getQrCodesByItems(List items) { + List qrCodeMasters = qrCodeMasterService.getByExtendIds(items.stream().map(WmsInCostcenterBackItem::getId).toList()); + items.removeIf(it -> qrCodeMasters.stream().anyMatch(qr -> qr.getExtendId().equals(it.getId()))); + if (CollectionUtil.isNotEmpty(items)) { + List qrNew = items.stream().map(it -> new WmsQrCodeMaster() + .setBarcodeCode(KeyUtil.next()) + .setProcessStage(BarCodeProcessStage.ForStorage.getState()) + .setBarcodeType(BarCodeType.CostcenterBack.getState()) + .setMaterialCode(it.getMatnr()) + .setMaterialDescription(it.getMaktx()) + .setPackagingType((short) 0) + .setQuantity(it.getNum()) + .setUnit(it.getMeins()) + .setBatchNo(serialNumberControllerService.generateInventoryInBatchNo(it.getMatnr())) + .setSerialNo("") + .setExtendId(it.getId()) + .setCreateUserId(UserUtil.getUserId()) + .setCreateUserName(UserUtil.getUserName()) + .setCreateTime(LocalDateTime.now()) + ).toList(); + qrCodeMasterService.saveBatch(qrNew); + qrCodeMasters.addAll(qrNew); + } + return qrCodeMasters; + } + + /** + * 导出物料标签图片ZIP + * @param id 订单ID + */ + @GetMapping(value = "exportItemImageZip", produces = "application/zip") + public ResponseEntity exportItemImageZip(@Valid @RequestParam @NotNull Long id) throws Exception { + WmsInCostcenterBack order = inCostcenterBackService.getById(id); + VUtil.trueThrowBusinessError(Objects.isNull(order)).throwMessage("订单不存在"); + List items = inCostcenterBackItemService.lambdaQuery() + .eq(WmsInCostcenterBackItem::getOrderId, id) + .list(); + List datas = convertToPrintDTO(getQrCodesByItems(items)); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (ZipOutputStream zos = new ZipOutputStream(baos)) { + for (QrCodeMasterPrintDTO it : datas) { + Map variables = new HashMap<>(); + variables.put("list", List.of(it)); + String html = ThymeleafUtil.generator("/template/qrcode/", "dp-1-label", ".html", variables); + ZipEntry entry = new ZipEntry(it.getBarcodeCode() + ".png"); + zos.putNextEntry(entry); + byte[] imageBytes = HtmlToImageUtil.convertToPng(html, 600); + zos.write(imageBytes, 0, imageBytes.length); + zos.closeEntry(); + } + } + byte[] zipBytes = baos.toByteArray(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.valueOf("application/zip")); + headers.setContentLength(zipBytes.length); + return new ResponseEntity<>(zipBytes, headers, HttpStatus.OK); + } } diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/constant/BarCodeType.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/constant/BarCodeType.java index 57fa7d86..2128b66a 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/constant/BarCodeType.java +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/constant/BarCodeType.java @@ -28,7 +28,11 @@ public enum BarCodeType { /** * 生产物料 */ - Production((short) 4, "生产物料"); + Production((short) 4, "生产物料"), + /** + * 成本中心退料 + */ + CostcenterBack((short) 5, "成本中心退料"); private final short state; private final String description;