package com.baiyue.warehouse.service; import com.baiyue.common.core.api.ResultCode; import com.baiyue.common.core.exception.BizException; import com.baiyue.warehouse.client.PrintPdfClient; import feign.FeignException; import jakarta.annotation.Resource; import java.math.BigDecimal; import java.nio.charset.StandardCharsets; import java.util.List; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.client.circuitbreaker.NoFallbackAvailableException; import org.springframework.http.ContentDisposition; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; @Service public class PalletLabelPrintService { @Resource private WarehouseResourceService resources; @Resource private DomesticWarehouseDirectory warehouses; @Resource private PrintPdfClient print; @Value("${baiyue.security.internal-service-token:${baiyue.internal-service.token}}") private String internalToken; public ResponseEntity print(long warehouseId, long palletId, String requestId) { var pallet = resources.pallet(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE, warehouseId, palletId); String code = pallet.getPalletCode(); // Keep the stored business code intact, including the QR payload. if (code == null || !code.matches("[\\x20-\\x7E]{1,34}") || code.isBlank()) { throw new BizException(ResultCode.VALIDATION_FAILED, "当前标签模板要求托盘编码为 1–34 位可打印 ASCII 字符,请核对托盘编码"); } var warehouse = warehouses.required(warehouseId); String fbaCode = pallet.getFbaWarehouseCode(); String fileName = code.replaceAll("[\\\\/:*?\"<>|]", "-") + "-托盘码.pdf"; var label = new PrintPdfClient.Label(code, fbaCode == null || fbaCode.isBlank() ? "—" : fbaCode, "PALLET", warehouse.warehouseName(), code); var request = new PrintPdfClient.Request("INBOUND_MARK_V1", new PrintPdfClient.PageSpec(new BigDecimal("100"), new BigDecimal("100")), fileName, List.of(label)); try { var response = print.generateInboundMarks(internalToken, requestId, request); byte[] body = response == null ? null : response.getBody(); MediaType type = response == null ? null : response.getHeaders().getContentType(); if (response == null || !response.getStatusCode().is2xxSuccessful() || body == null || body.length == 0 || type == null || !MediaType.APPLICATION_PDF.isCompatibleWith(type)) { throw new BizException(ResultCode.SERVICE_UNAVAILABLE, "打印服务未返回有效 PDF,请稍后重试"); } return ResponseEntity.ok().contentType(MediaType.APPLICATION_PDF).contentLength(body.length) .header(HttpHeaders.CONTENT_DISPOSITION, ContentDisposition.attachment().filename(fileName, StandardCharsets.UTF_8).build().toString()) .header(HttpHeaders.CACHE_CONTROL, "no-store").body(body); } catch (FeignException | NoFallbackAvailableException exception) { throw new BizException(ResultCode.SERVICE_UNAVAILABLE, "打印服务暂不可用,请稍后重试"); } } }