feat(export): 添加导出标签图片ZIP功能并优化标签样式
- 在库存物料条码打印接口中新增导出物料标签图片ZIP接口,支持批量生成PNG图片压缩包 - 新增HtmlToImageUtil工具类,使用wkhtmltoimage将HTML转换为PNG图片 - 在储位管理中新增导出标签ZIP接口,实现储位二维码批量导出功能 - 普通物料订单及生产订单相关控制器新增导出物料标签图片ZIP接口,支持订单物料标签图片批量下载 - 生产订单副产品管理新增导出物料标签图片ZIP接口,支持副产品标签导出为ZIP - 优化二维码标签HTML模板(dp-1.html、qitao.html、spitem.html),调整尺寸和样式以适配打印需求 - 公共DTO类DeliverNormalOrderItemDTO添加打印名称字段printLabel,标签中显示以改善展示信息 - 相关接口返回Content-Type设为application/zip,支持ZIP文件响应UI下载体验
This commit is contained in:
parent
81b9f5c7bb
commit
2c9c0db974
|
|
@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil;
|
|||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.nflg.wms.admin.util.HtmlToImageUtil;
|
||||
import com.nflg.wms.admin.util.PdfGeneratorUtil;
|
||||
import com.nflg.wms.admin.util.QRCodeUtil;
|
||||
import com.nflg.wms.admin.util.ThymeleafUtil;
|
||||
|
|
@ -34,7 +35,9 @@ 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 org.springframework.web.multipart.MultipartFile;
|
||||
|
|
@ -52,6 +55,8 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* 库存物料条码打印
|
||||
|
|
@ -202,7 +207,7 @@ public class BarcodePrintingController extends BaseController {
|
|||
@PostMapping("exportMaterialsPdf")
|
||||
public void exportMaterials(HttpServletResponse response, @Valid @RequestBody @NotNull BarcodePrintingIdsQO request) throws Exception {
|
||||
List<WmsInventoryBarcodePrinting> codelist = printingService.listByIds(request.getIds());
|
||||
VUtil.trueThrowBusinessError(Objects.isNull(codelist)).throwMessage("订单不存在");
|
||||
VUtil.trueThrowBusinessError(Objects.isNull(codelist)).throwMessage("物料不存在");
|
||||
List<DeliverNormalOrderItemDTO> datas = new ArrayList<>();
|
||||
// Integer i = 1;
|
||||
for (WmsInventoryBarcodePrinting item : codelist) {
|
||||
|
|
@ -223,7 +228,7 @@ public class BarcodePrintingController extends BaseController {
|
|||
dto.setRowNo("");
|
||||
dto.setPrintNo(IdUtil.getSnowflakeNextIdStr());
|
||||
dto.setPrintNum("1");
|
||||
String qCode = QRCodeUtil.generateQRCodeBase64(generateQRContent(dto, serialNumber), 100, 100);
|
||||
String qCode = QRCodeUtil.generateQRCodeBase64(generateQRContent(dto, serialNumber), 100, 100);
|
||||
dto.setQrCode(qCode);
|
||||
datas.add(dto);
|
||||
//i += 1;
|
||||
|
|
@ -254,13 +259,89 @@ public class BarcodePrintingController extends BaseController {
|
|||
Map<String, Object> variables = new HashMap<>();
|
||||
variables.put("list", datas);
|
||||
if (Objects.equals(request.getType(), 1)) {
|
||||
String html = ThymeleafUtil.generator("/template/qrcode/", "Inv-1", ".html", variables);
|
||||
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/", "Inv-2", ".html", variables);
|
||||
String html = ThymeleafUtil.generator("/template/qrcode/", "dp-2", ".html", variables);
|
||||
URL baseUrl = new ClassPathResource("template/qrcode/").getURL();
|
||||
PdfGeneratorUtil.generatePdf("库存物料条码(整张)", html, baseUrl.toString(), response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出物料标签图片ZIP
|
||||
* @param ids id列表
|
||||
*/
|
||||
@PostMapping(value = "exportItemImageZip", produces = "application/zip")
|
||||
public ResponseEntity<byte[]> exportItemImageZip(@RequestBody @NotEmpty List<Long> ids) throws Exception {
|
||||
List<WmsInventoryBarcodePrinting> codelist = printingService.listByIds(ids);
|
||||
VUtil.trueThrowBusinessError(Objects.isNull(codelist)).throwMessage("物料不存在");
|
||||
List<DeliverNormalOrderItemDTO> datas = new ArrayList<>();
|
||||
// Integer i = 1;
|
||||
for (WmsInventoryBarcodePrinting item : codelist) {
|
||||
if (StrUtil.isNotBlank(item.getSerialNumbers())) {
|
||||
List<String> serialNumbers = StrUtil.split(item.getSerialNumbers(), ",");
|
||||
for (String serialNumber : serialNumbers) {
|
||||
DeliverNormalOrderItemDTO dto = new DeliverNormalOrderItemDTO();
|
||||
dto.setMaterialNo(item.getMaterialNo());
|
||||
dto.setMaterialDesc(item.getMaterialDes());
|
||||
dto.setBatchNo(StrUtil.isBlank(item.getBatchNumber()) ? "" : item.getBatchNumber());
|
||||
dto.setExternalOrderNo("");
|
||||
dto.setRowNo("");
|
||||
dto = new DeliverNormalOrderItemDTO();
|
||||
dto.setMaterialNo(item.getMaterialNo());
|
||||
dto.setMaterialDesc(item.getMaterialDes());
|
||||
dto.setBatchNo(StrUtil.isBlank(item.getBatchNumber()) ? "" : item.getBatchNumber());
|
||||
dto.setExternalOrderNo("");
|
||||
dto.setRowNo("");
|
||||
dto.setPrintNo(IdUtil.getSnowflakeNextIdStr());
|
||||
dto.setPrintNum("1");
|
||||
String qCode = QRCodeUtil.generateQRCodeBase64(generateQRContent(dto, serialNumber), 100, 100);
|
||||
dto.setQrCode(qCode);
|
||||
datas.add(dto);
|
||||
//i += 1;
|
||||
}
|
||||
} else {
|
||||
int codeNum = item.getQty().divide(item.getPackingNum(), 0, RoundingMode.UP).intValue();
|
||||
for (int j = 0; j < codeNum; j++) {
|
||||
DeliverNormalOrderItemDTO dto = new DeliverNormalOrderItemDTO();
|
||||
dto.setMaterialNo(item.getMaterialNo());
|
||||
dto.setMaterialDesc(item.getMaterialDes());
|
||||
dto.setBatchNo(StrUtil.isBlank(item.getBatchNumber()) ? "" : item.getBatchNumber());
|
||||
dto.setExternalOrderNo("");
|
||||
dto.setRowNo("");
|
||||
dto = new DeliverNormalOrderItemDTO();
|
||||
dto.setMaterialNo(item.getMaterialNo());
|
||||
dto.setMaterialDesc(item.getMaterialDes());
|
||||
dto.setBatchNo(StrUtil.isBlank(item.getBatchNumber()) ? "" : item.getBatchNumber());
|
||||
dto.setExternalOrderNo("");
|
||||
dto.setRowNo("");
|
||||
dto.setPrintNo(IdUtil.getSnowflakeNextIdStr());
|
||||
dto.setPrintNum(item.getPackingNum().toString());
|
||||
String qCode = QRCodeUtil.generateQRCodeBase64(generateQRContent(dto, ""), 100, 100);
|
||||
dto.setQrCode(qCode);
|
||||
datas.add(dto);
|
||||
}
|
||||
}
|
||||
}
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
|
||||
for (DeliverNormalOrderItemDTO it : datas) {
|
||||
Map<String, Object> variables = new HashMap<>();
|
||||
variables.put("list", datas);
|
||||
String html = ThymeleafUtil.generator("/template/qrcode/", "dp-1", ".html", variables);
|
||||
ZipEntry entry = new ZipEntry(it.getPrintNo() + ".png");
|
||||
zos.putNextEntry(entry);
|
||||
byte[] imageBytes = HtmlToImageUtil.convertToPng(html, 60);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import jakarta.servlet.http.HttpServletResponse;
|
|||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
|
@ -115,6 +116,15 @@ public class BinController extends BaseController {
|
|||
binControllerService.exportPdf(response, ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出标签ZIP
|
||||
* @param ids 储位id列表
|
||||
*/
|
||||
@PostMapping("exportZip")
|
||||
public ResponseEntity<byte[]> exportZip(@Valid @RequestBody @NotEmpty List<Long> ids) throws Exception {
|
||||
return binControllerService.exportZip(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取库存信息
|
||||
* @param warehouseId 仓库id
|
||||
|
|
|
|||
|
|
@ -10,10 +10,7 @@ import com.nflg.wms.admin.repository.InMaterialScanRecordRespository;
|
|||
import com.nflg.wms.admin.service.BasdeSerialNumberControllerService;
|
||||
import com.nflg.wms.admin.service.BinService;
|
||||
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.Constant;
|
||||
import com.nflg.wms.common.pojo.ApiResult;
|
||||
import com.nflg.wms.common.pojo.PageData;
|
||||
|
|
@ -35,15 +32,22 @@ 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;
|
||||
|
||||
/**
|
||||
* 生产订单入库管理
|
||||
|
|
@ -242,6 +246,65 @@ public class InProduceOrderController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出物料标签图片ZIP
|
||||
* @param id 订单ID
|
||||
*/
|
||||
@GetMapping(value = "exportItemImageZip", produces = "application/zip")
|
||||
public ResponseEntity<byte[]> exportItemImageZip(@Valid @RequestParam @NotNull Long id) throws Exception {
|
||||
WmsInProduceOrder order = produceOrderService.getById(id);
|
||||
VUtil.trueThrowBusinessError(Objects.isNull(order)).throwMessage("订单不存在");
|
||||
List<WmsInProduceOrderItem> list = produceOrderItemService.getByOrderId(id);
|
||||
if (order.getList()) {
|
||||
list.removeIf(item -> Objects.equals(item.getParentId(), 0L));
|
||||
}
|
||||
List<DeliverNormalOrderItemDTO> datas = new ArrayList<>();
|
||||
for (WmsInProduceOrderItem item : list) {
|
||||
BigDecimal[] result = item.getNum().divideAndRemainder(BigDecimal.ONE);
|
||||
for (int i = 0, count = result[0].intValue(); i < count; i++) {
|
||||
DeliverNormalOrderItemDTO dto = new DeliverNormalOrderItemDTO();
|
||||
dto.setMaterialNo(item.getMaterialNo());
|
||||
dto.setMaterialDesc(item.getMaterialDesc());
|
||||
dto.setExternalOrderNo(order.getOrderNo());
|
||||
dto.setRowNo("");
|
||||
dto.setIndex(i);
|
||||
dto.setPrintNo(IdUtil.getSnowflakeNextIdStr());
|
||||
dto.setPrintLabel("自制件");
|
||||
if (i == count - 1 && result[1].compareTo(BigDecimal.ZERO) > 0) {
|
||||
dto.setPrintNum(DF.format(result[1]));
|
||||
} else {
|
||||
dto.setPrintNum(DF.format(BigDecimal.ONE));
|
||||
}
|
||||
dto.setSupplierCode("");
|
||||
dto.setBatchNo(item.getBatchNo());
|
||||
dto.setQrCode(QRCodeUtil.generateQRCodeBase64(generateQRContent(dto, ""), 100, 100));
|
||||
datas.add(dto);
|
||||
}
|
||||
}
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
|
||||
for (DeliverNormalOrderItemDTO it : datas) {
|
||||
Map<String, Object> variables = new HashMap<>();
|
||||
variables.put("list", datas);
|
||||
String html = ThymeleafUtil.generator("/template/qrcode/", "dp-1", ".html", variables);
|
||||
// HtmlToImageUtil.convertToPng(html, 800);
|
||||
// response.setContentType("image/png");
|
||||
// response.getOutputStream().write(HtmlToImageUtil.convertToPng(html, 60));
|
||||
// break;
|
||||
ZipEntry entry = new ZipEntry(it.getPrintNo() + ".png");
|
||||
zos.putNextEntry(entry);
|
||||
byte[] imageBytes = HtmlToImageUtil.convertToPng(html, 60);
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出报工单PDF(单个)
|
||||
* @param id 订单id
|
||||
|
|
|
|||
|
|
@ -10,10 +10,7 @@ import com.nflg.wms.admin.pojo.dto.PdfPageDTO;
|
|||
import com.nflg.wms.admin.repository.InMaterialScanRecordRespository;
|
||||
import com.nflg.wms.admin.service.BasdeSerialNumberControllerService;
|
||||
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.pojo.ApiResult;
|
||||
import com.nflg.wms.common.pojo.PageData;
|
||||
import com.nflg.wms.common.pojo.document.InMaterialScanRecord;
|
||||
|
|
@ -37,15 +34,22 @@ 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;
|
||||
|
||||
/**
|
||||
* 生产订单副产品(拆解)管理
|
||||
|
|
@ -371,6 +375,62 @@ public class InProduceOrderSurplusController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出物料标签图片ZIP
|
||||
* @param id 订单ID
|
||||
*/
|
||||
@GetMapping(value = "exportItemImageZip", produces = "application/zip")
|
||||
public ResponseEntity<byte[]> exportItemImageZip(@Valid @RequestParam @NotNull Long id) throws Exception {
|
||||
WmsInProduceOrderSurplus order = inProduceOrderSurplusService.getById(id);
|
||||
VUtil.trueThrowBusinessError(Objects.isNull(order)).throwMessage("订单不存在");
|
||||
List<WmsInProduceOrderSurplusItem> list = inProduceOrderSurplusItemService.getList(id);
|
||||
List<DeliverNormalOrderItemDTO> datas = new ArrayList<>();
|
||||
for (WmsInProduceOrderSurplusItem item : list) {
|
||||
BigDecimal[] result = item.getNum().divideAndRemainder(BigDecimal.ONE);
|
||||
for (int i = 0, count = result[0].intValue(); i < count; i++) {
|
||||
DeliverNormalOrderItemDTO dto = new DeliverNormalOrderItemDTO();
|
||||
dto.setMaterialNo(item.getMatnr());
|
||||
dto.setMaterialDesc(item.getMaktx2());
|
||||
dto.setExternalOrderNo(order.getAufnr());
|
||||
dto.setRowNo("");
|
||||
dto.setIndex(i);
|
||||
dto.setPrintNo(IdUtil.getSnowflakeNextIdStr());
|
||||
dto.setPrintLabel("自制件");
|
||||
if (i == count - 1 && result[1].compareTo(BigDecimal.ZERO) > 0) {
|
||||
dto.setPrintNum(DF.format(result[1]));
|
||||
} else {
|
||||
dto.setPrintNum(DF.format(BigDecimal.ONE));
|
||||
}
|
||||
dto.setSupplierCode("");
|
||||
dto.setBatchNo("");
|
||||
dto.setQrCode(QRCodeUtil.generateQRCodeBase64(generateQRContent(dto, ""), 100, 100));
|
||||
datas.add(dto);
|
||||
}
|
||||
}
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
|
||||
for (DeliverNormalOrderItemDTO it : datas) {
|
||||
Map<String, Object> variables = new HashMap<>();
|
||||
variables.put("list", datas);
|
||||
String html = ThymeleafUtil.generator("/template/qrcode/", "dp-1", ".html", variables);
|
||||
// HtmlToImageUtil.convertToPng(html, 800);
|
||||
// response.setContentType("image/png");
|
||||
// response.getOutputStream().write(HtmlToImageUtil.convertToPng(html, 60));
|
||||
// break;
|
||||
ZipEntry entry = new ZipEntry(it.getPrintNo() + ".png");
|
||||
zos.putNextEntry(entry);
|
||||
byte[] imageBytes = HtmlToImageUtil.convertToPng(html, 60);
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出拆解单
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -6,10 +6,7 @@ import cn.hutool.core.util.StrUtil;
|
|||
import com.nflg.wms.admin.pojo.dto.SAPMaterialInfoInOrderDTO;
|
||||
import com.nflg.wms.admin.service.BasdeSerialNumberControllerService;
|
||||
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.pojo.ApiResult;
|
||||
import com.nflg.wms.common.pojo.PageData;
|
||||
import com.nflg.wms.common.pojo.dto.DeliverNormalOrderItemDTO;
|
||||
|
|
@ -36,14 +33,21 @@ 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.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* 普通物料订单管理
|
||||
|
|
@ -181,6 +185,7 @@ public class NormalOrderController extends BaseController {
|
|||
DeliverNormalOrderItemDTO dto = Convert.convert(DeliverNormalOrderItemDTO.class, order);
|
||||
dto.setIndex(i);
|
||||
dto.setPrintNo(order.getId() + "-" + i);
|
||||
dto.setPrintLabel(dto.getPrintNo());
|
||||
if (i == order.getLableNum() - 1) {
|
||||
BigDecimal n = order.getBatchNum().divideAndRemainder(order.getMinPackageNum())[1];
|
||||
if (n.compareTo(BigDecimal.ZERO) == 0) {
|
||||
|
|
@ -270,6 +275,7 @@ public class NormalOrderController extends BaseController {
|
|||
dto.setBatchNo(NoUtil.getBatchNo(supplierNo));
|
||||
dto.setIndex(i);
|
||||
dto.setPrintNo(order.getId() + "-" + i);
|
||||
dto.setPrintLabel(dto.getPrintNo());
|
||||
if (i == order.getLableNum() - 1) {
|
||||
BigDecimal n = order.getBatchNum().divideAndRemainder(order.getMinPackageNum())[1];
|
||||
if (n.compareTo(BigDecimal.ZERO) == 0) {
|
||||
|
|
@ -303,4 +309,48 @@ public class NormalOrderController extends BaseController {
|
|||
URL baseUrl = new ClassPathResource("template/qrcode/").getURL();
|
||||
PdfGeneratorUtil.generatePdf("普通物料条码(整张)", html, baseUrl.toString(), response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出采购单物料图片ZIP
|
||||
* @param ids 要打印的id列表
|
||||
*/
|
||||
@PostMapping(value = "exportOrderItemImageZip", produces = "application/zip")
|
||||
public ResponseEntity<byte[]> exportOrderItemImageZip(@Valid @RequestBody @NotNull List<Long> ids) throws Exception {
|
||||
List<DeliverNormalOrderVO> orders = deliverNormalOrderService.getList(ids);
|
||||
VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(orders)).throwMessage("没有需要打印的数据");
|
||||
return exportItemImageZip(convert(orders));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出打印送货单物料图片ZIP
|
||||
* @param datas 要打印的数据
|
||||
*/
|
||||
@PostMapping(value = "deliver/exportOrderItemImageZip", produces = "application/zip")
|
||||
public void exportDeliverOrderPdfPerPage(@Valid @RequestBody @NotEmpty List<DeliverNormalOrderSaveItemQO> datas) throws Exception {
|
||||
exportItemImageZip(convert1(datas.get(0).getSupplierNo(), datas));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出标签图片ZIP
|
||||
*/
|
||||
private ResponseEntity<byte[]> exportItemImageZip(List<DeliverNormalOrderItemDTO> list) throws Exception {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
|
||||
for (DeliverNormalOrderItemDTO it : list) {
|
||||
Map<String, Object> variables = new HashMap<>();
|
||||
variables.put("list", List.of(it));
|
||||
String html = ThymeleafUtil.generator("/template/qrcode/", "dp-1", ".html", variables);
|
||||
ZipEntry entry = new ZipEntry(it.getPrintNo() + ".png");
|
||||
zos.putNextEntry(entry);
|
||||
byte[] imageBytes = HtmlToImageUtil.convertToPng(html, 60);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -22,10 +22,7 @@ import com.nflg.wms.admin.service.BasdeSerialNumberControllerService;
|
|||
import com.nflg.wms.admin.service.BinService;
|
||||
import com.nflg.wms.admin.service.SapService;
|
||||
import com.nflg.wms.admin.service.StructuralPackageControllerService;
|
||||
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.OrderState;
|
||||
import com.nflg.wms.common.constant.STATE;
|
||||
import com.nflg.wms.common.exception.NflgException;
|
||||
|
|
@ -51,7 +48,9 @@ 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 org.springframework.web.multipart.MultipartFile;
|
||||
|
|
@ -71,6 +70,8 @@ import java.time.LocalDate;
|
|||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* 钢构件订单管理
|
||||
|
|
@ -456,13 +457,14 @@ public class StructuralPackageOrderController extends BaseController {
|
|||
for (DeliverStructuralPackageOrderTrayItemVO it : list) {
|
||||
for (int i = 0, count = it.getShipmentNum().intValue(); i < count; i++) {
|
||||
DeliverStructuralPackageOrderTrayItemVO vo = BeanUtil.copy(it, DeliverStructuralPackageOrderTrayItemVO.class);
|
||||
vo.setQrCodeId(it.getId() + "-" + (i + 1));
|
||||
vo.setQrCode(it.getId() + "-" + (i + 1) + "^" + it.getMaterialNo() + "_" + it.getTrayNo() + "_1");
|
||||
vo.setQrCodeImage(QRCodeUtil.generateQRCodeBase64(vo.getQrCode(), 200, 200));
|
||||
datas.add(vo);
|
||||
}
|
||||
|
||||
if (it.getShipmentNum().remainder(BigDecimal.ONE).compareTo(BigDecimal.ZERO) > 0) {
|
||||
DeliverStructuralPackageOrderTrayItemVO vo = BeanUtil.copy(it, DeliverStructuralPackageOrderTrayItemVO.class);
|
||||
vo.setQrCodeId(it.getId() + "-" + (it.getShipmentNum().intValue() + 1));
|
||||
vo.setQrCode(it.getId() + "-" + (it.getShipmentNum().intValue() + 1) + "^" + it.getMaterialNo() + "_" + it.getTrayNo() + "_" + it.getShipmentNum().remainder(BigDecimal.ONE));
|
||||
vo.setQrCodeImage(QRCodeUtil.generateQRCodeBase64(vo.getQrCode(), 200, 200));
|
||||
datas.add(vo);
|
||||
|
|
@ -476,6 +478,59 @@ public class StructuralPackageOrderController extends BaseController {
|
|||
PdfGeneratorUtil.generatePdf(trayVO.getExternalOrderNo() + "-" + trayVO.getWorkbenchCode() + "标签", html, baseUrl.toString(), response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出零件标签图片ZIP
|
||||
* @param id 托盘id
|
||||
*/
|
||||
@GetMapping(value = "exportItemImageZip", produces = "application/zip")
|
||||
public ResponseEntity<byte[]> exportItemImageZip(HttpServletResponse response, @Valid @RequestParam @NotNull Long id) throws Exception {
|
||||
DeliverStructuralPackageOrderExtendVO trayVO = deliverStructuralPackageOrderTrayService.getInfo(id);
|
||||
VUtil.trueThrowBusinessError(Objects.isNull(trayVO)).throwMessage("数据不存在");
|
||||
List<DeliverStructuralPackageOrderTrayItemVO> list = deliverStructuralPackageOrderTrayItemService.getListVOByTrayId(id);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
|
||||
List<DeliverStructuralPackageOrderTrayItemVO> datas = new ArrayList<>();
|
||||
int index = 0;
|
||||
for (DeliverStructuralPackageOrderTrayItemVO it : list) {
|
||||
datas.clear();
|
||||
index++;
|
||||
for (int i = 0, count = it.getShipmentNum().intValue(); i < count; i++) {
|
||||
DeliverStructuralPackageOrderTrayItemVO vo = BeanUtil.copy(it, DeliverStructuralPackageOrderTrayItemVO.class);
|
||||
vo.setQrCodeId(it.getId() + "-" + (i + 1));
|
||||
vo.setQrCode(it.getId() + "-" + (i + 1) + "^" + it.getMaterialNo() + "_" + it.getTrayNo() + "_1");
|
||||
vo.setQrCodeImage(QRCodeUtil.generateQRCodeBase64(vo.getQrCode(), 200, 200));
|
||||
datas.add(vo);
|
||||
}
|
||||
if (it.getShipmentNum().remainder(BigDecimal.ONE).compareTo(BigDecimal.ZERO) > 0) {
|
||||
DeliverStructuralPackageOrderTrayItemVO vo = BeanUtil.copy(it, DeliverStructuralPackageOrderTrayItemVO.class);
|
||||
vo.setQrCodeId(it.getId() + "-" + (it.getShipmentNum().intValue() + 1));
|
||||
vo.setQrCode(it.getId() + "-" + (it.getShipmentNum().intValue() + 1) + "^" + it.getMaterialNo() + "_" + it.getTrayNo() + "_" + it.getShipmentNum().remainder(BigDecimal.ONE));
|
||||
vo.setQrCodeImage(QRCodeUtil.generateQRCodeBase64(vo.getQrCode(), 200, 200));
|
||||
datas.add(vo);
|
||||
}
|
||||
Map<String, Object> variables = new HashMap<>();
|
||||
variables.put("list", datas);
|
||||
variables.put("info", trayVO);
|
||||
variables.put("index", index);
|
||||
String html = ThymeleafUtil.generator("/template/qrcode/", "spitem", ".html", variables);
|
||||
// HtmlToImageUtil.convertToPng(html, 800);
|
||||
// response.setContentType("image/png");
|
||||
// response.getOutputStream().write(HtmlToImageUtil.convertToPng(html, 60));
|
||||
// break;
|
||||
ZipEntry entry = new ZipEntry(it.getId() + ".png");
|
||||
zos.putNextEntry(entry);
|
||||
byte[] imageBytes = HtmlToImageUtil.convertToPng(html, 60);
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出托盘标签PDF
|
||||
* @param id 托盘id
|
||||
|
|
@ -492,6 +547,25 @@ public class StructuralPackageOrderController extends BaseController {
|
|||
PdfGeneratorUtil.generatePdf("托盘标签" + trayVO.getTrayNo(), html, baseUrl.toString(), response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出托盘标签图片
|
||||
* @param id 托盘id
|
||||
*/
|
||||
@GetMapping(value = "exportTrayImage", produces = MediaType.IMAGE_PNG_VALUE)
|
||||
public ResponseEntity<byte[]> exportTrayImage(@Valid @RequestParam @NotNull Long id) throws Exception {
|
||||
DeliverStructuralPackageOrderExtendVO trayVO = deliverStructuralPackageOrderTrayService.getInfo(id);
|
||||
VUtil.trueThrowBusinessError(Objects.isNull(trayVO)).throwMessage("数据不存在");
|
||||
trayVO.setQrCode(QRCodeUtil.generateQRCodeBase64(trayVO.getTrayNo(), 100, 100));
|
||||
Map<String, Object> variables = new HashMap<>();
|
||||
variables.put("info", trayVO);
|
||||
String html = ThymeleafUtil.generator("/template/qrcode/", "tray", ".html", variables);
|
||||
byte[] imageBytes = HtmlToImageUtil.convertToPng(html, 60);
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.IMAGE_PNG);
|
||||
headers.setContentLength(imageBytes.length);
|
||||
return new ResponseEntity<>(imageBytes, headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出齐套标签PDF
|
||||
* @param id 托盘id
|
||||
|
|
@ -510,6 +584,27 @@ public class StructuralPackageOrderController extends BaseController {
|
|||
PdfGeneratorUtil.generatePdf("齐套标签" + trayVO.getTrayNo(), html, baseUrl.toString(), response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出齐套标签图片
|
||||
* @param id 托盘id
|
||||
*/
|
||||
@GetMapping(value = "exportQiTaoImage", produces = MediaType.IMAGE_PNG_VALUE)
|
||||
public ResponseEntity<byte[]> exportQiTaoImage(@Valid @RequestParam @NotNull Long id) throws Exception {
|
||||
DeliverStructuralPackageOrderExtendVO trayVO = deliverStructuralPackageOrderTrayService.getInfo(id);
|
||||
VUtil.trueThrowBusinessError(Objects.isNull(trayVO)).throwMessage("数据不存在");
|
||||
String temp = trayVO.getExternalOrderNo() + "$" + trayVO.getRowNo() + "$" + trayVO.getPackageNo();
|
||||
String uniqueCode = DigestUtil.md5Hex(temp);
|
||||
trayVO.setQrCode(QRCodeUtil.generateQRCodeBase64(uniqueCode + "$" + temp, 100, 100));
|
||||
Map<String, Object> variables = new HashMap<>();
|
||||
variables.put("info", trayVO);
|
||||
String html = ThymeleafUtil.generator("/template/qrcode/", "qitao", ".html", variables);
|
||||
byte[] imageBytes = HtmlToImageUtil.convertToPng(html, 60);
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.IMAGE_PNG);
|
||||
headers.setContentLength(imageBytes.length);
|
||||
return new ResponseEntity<>(imageBytes, headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据托盘号获取托盘信息(PDA使用)
|
||||
*/
|
||||
|
|
@ -1054,10 +1149,6 @@ public class StructuralPackageOrderController extends BaseController {
|
|||
} else if (!DateTimeUtil.isValidDate(expectDeliveryDate)) {
|
||||
sb.append("期望交期无效;");
|
||||
}
|
||||
String rowNo = StrUtil.trim(data.get("行项目*").toString());
|
||||
if (StrUtil.isBlank(rowNo)) {
|
||||
sb.append("行项目不能为空;");
|
||||
}
|
||||
String snum = StrUtil.trim(data.get("数量*").toString());
|
||||
BigDecimal num = null;
|
||||
if (StrUtil.isBlank(snum)) {
|
||||
|
|
@ -1071,6 +1162,7 @@ public class StructuralPackageOrderController extends BaseController {
|
|||
}
|
||||
}
|
||||
String poNum = StrUtil.trim(data.get("采购订单号*").toString());
|
||||
String rowNo = StrUtil.trim(data.get("行项目*").toString());
|
||||
BigDecimal transportNum = num;
|
||||
if (StrUtil.isBlank(poNum)) {
|
||||
sb.append("采购订单号不能为空;");
|
||||
|
|
@ -1081,6 +1173,9 @@ public class StructuralPackageOrderController extends BaseController {
|
|||
if (CollectionUtil.isEmpty(orders)) {
|
||||
sb.append("采购订单号无效;");
|
||||
} else {
|
||||
if (StrUtil.isBlank(rowNo)) {
|
||||
sb.append("行项目不能为空;");
|
||||
}
|
||||
SAPMaterialInfoInOrderDTO order = orders.stream()
|
||||
.filter(it -> StrUtil.equals(it.getEbelp(), rowNo))
|
||||
.findFirst()
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import cn.hutool.core.convert.Convert;
|
|||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.nflg.wms.admin.util.HtmlToImageUtil;
|
||||
import com.nflg.wms.admin.util.PdfGeneratorUtil;
|
||||
import com.nflg.wms.admin.util.QRCodeUtil;
|
||||
import com.nflg.wms.admin.util.ThymeleafUtil;
|
||||
|
|
@ -36,8 +37,11 @@ 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.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
|
@ -53,7 +57,10 @@ import java.time.LocalDate;
|
|||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class BinControllerService {
|
||||
|
||||
|
|
@ -102,14 +109,14 @@ public class BinControllerService {
|
|||
if (updateCheckAndImport(data)) {
|
||||
return ApiResult.success();
|
||||
} else {
|
||||
try(ByteArrayOutputStream osOut = new ByteArrayOutputStream()) {
|
||||
try (ByteArrayOutputStream osOut = new ByteArrayOutputStream()) {
|
||||
new Workbook()
|
||||
.addSheet(new ListSheet<>(data))
|
||||
.writeTo(osOut);
|
||||
try(ByteArrayInputStream isIn = new ByteArrayInputStream(osOut.toByteArray())) {
|
||||
try (ByteArrayInputStream isIn = new ByteArrayInputStream(osOut.toByteArray())) {
|
||||
return ApiResult.error(STATE.DataNoCheckPass, "导入文件失败", fileUploadService.upload("temp/" + DateTimeUtil.format(LocalDate.now(), "yyyyMMdd") + "/" + IdUtil.fastUUID() + ".xlsx", isIn, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
|
||||
}
|
||||
}catch (Exception e){
|
||||
} catch (Exception e) {
|
||||
return ApiResult.error(STATE.BusinessError, "保存文件出错");
|
||||
}
|
||||
}
|
||||
|
|
@ -155,9 +162,9 @@ public class BinControllerService {
|
|||
bin.setUpdateTime(LocalDateTime.now());
|
||||
}
|
||||
}
|
||||
if (StrUtil.isBlank(dto.getName())){
|
||||
if (StrUtil.isBlank(dto.getName())) {
|
||||
sb.append("仓库名称不能为空;");
|
||||
}else {
|
||||
} else {
|
||||
bin.setName(dto.getName());
|
||||
}
|
||||
bin.setRemark(dto.getRemark());
|
||||
|
|
@ -206,8 +213,10 @@ public class BinControllerService {
|
|||
List<WmsBin> bins = wmsBinService.listByIds(ids);
|
||||
Map<String, Object> variables = new HashMap<>();
|
||||
variables.put("datas", bins.stream().map(bin -> new QRCodeDTO()
|
||||
.setNo(bin.getNo())
|
||||
.setQrCode(QRCodeUtil.generateQRCodeBase64(bin.getNo(), 100, 100))));
|
||||
.setNo(bin.getNo())
|
||||
.setQrCode(QRCodeUtil.generateQRCodeBase64(bin.getNo(), 100, 100))
|
||||
).toList()
|
||||
);
|
||||
String html = ThymeleafUtil.generator("/template/", "储位二维码", ".html", variables);
|
||||
PdfGeneratorUtil.generatePdf("储位二维码", html, response);
|
||||
}
|
||||
|
|
@ -215,4 +224,30 @@ public class BinControllerService {
|
|||
public List<BinInventoryVO> getInventory(Long warehouseId) {
|
||||
return wmsBinService.getInventory(warehouseId);
|
||||
}
|
||||
|
||||
public ResponseEntity<byte[]> exportZip(@Valid @NotEmpty List<Long> ids) throws Exception {
|
||||
List<WmsBin> bins = wmsBinService.listByIds(ids);
|
||||
List<QRCodeDTO> datas = bins.stream().map(bin -> new QRCodeDTO()
|
||||
.setNo(bin.getNo())
|
||||
.setQrCode(QRCodeUtil.generateQRCodeBase64(bin.getNo(), 100, 100)))
|
||||
.toList();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
|
||||
for (QRCodeDTO it : datas) {
|
||||
Map<String, Object> variables = new HashMap<>();
|
||||
variables.put("datas", List.of(it));
|
||||
String html = ThymeleafUtil.generator("/template/", "储位二维码", ".html", variables);
|
||||
ZipEntry entry = new ZipEntry(it.getNo() + ".png");
|
||||
zos.putNextEntry(entry);
|
||||
byte[] imageBytes = HtmlToImageUtil.convertToPng(html, 40);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
package com.nflg.wms.admin.util;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
public class HtmlToImageUtil {
|
||||
|
||||
/**
|
||||
* 将HTML内容转换为PNG图片
|
||||
* @param htmlContent HTML内容
|
||||
* @param width 图片宽度,单位mm
|
||||
* @return PNG图片字节数组
|
||||
* @throws Exception 转换异常
|
||||
*/
|
||||
public static byte[] convertToPng(String htmlContent, int width) throws Exception {
|
||||
Path inputHtmlPath = null, outputImgPath = null;
|
||||
try {
|
||||
Path tempDir = Paths.get(System.getProperty("java.io.tmpdir"), "wkhtml");
|
||||
if (!Files.exists(tempDir)) {
|
||||
Files.createDirectories(tempDir);
|
||||
}
|
||||
long t = System.currentTimeMillis();
|
||||
inputHtmlPath = tempDir.resolve("input_" + t + ".html");
|
||||
outputImgPath = tempDir.resolve("output_" + t + ".png");
|
||||
Files.write(inputHtmlPath, htmlContent.getBytes());
|
||||
List<String> command = new ArrayList<>();
|
||||
command.add("wkhtmltoimage");
|
||||
// 可选参数:设置宽度 (例如 1200px)
|
||||
command.add("--width");
|
||||
command.add(String.valueOf((int) (width * 3.78)));
|
||||
// 可选参数:指定图片类型 (例如 PNG)
|
||||
command.add("--format");
|
||||
command.add("png");
|
||||
//质量
|
||||
command.add("--quality");
|
||||
command.add("100");
|
||||
// 输入文件路径
|
||||
command.add(inputHtmlPath.toAbsolutePath().toString());
|
||||
// 输出文件路径
|
||||
command.add(outputImgPath.toAbsolutePath().toString());
|
||||
ProcessBuilder builder = new ProcessBuilder(command);
|
||||
Process process = builder.start();
|
||||
int exitCode = process.waitFor();
|
||||
if (exitCode != 0) {
|
||||
// 读取错误流,帮助调试
|
||||
String error = new String(process.getErrorStream().readAllBytes());
|
||||
throw new IOException("html转换图片失败,退出码: " + exitCode + ", 错误信息: " + error);
|
||||
}
|
||||
return FileUtil.readBytes(outputImgPath);
|
||||
} finally {
|
||||
if (Objects.nonNull(inputHtmlPath)) {
|
||||
Files.deleteIfExists(inputHtmlPath);
|
||||
}
|
||||
if (Objects.nonNull(outputImgPath)) {
|
||||
Files.deleteIfExists(outputImgPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,22 +6,19 @@
|
|||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<style>
|
||||
@page {
|
||||
size: A4;
|
||||
margin: 5mm; /* 关键!清除默认页边距 */
|
||||
}
|
||||
@media print {
|
||||
body {
|
||||
font-size: 9pt;
|
||||
}
|
||||
size: 60mm 40mm;
|
||||
margin: 0;
|
||||
}
|
||||
body {
|
||||
width: 58mm;
|
||||
height: 38mm;
|
||||
font-size: 8pt;
|
||||
font-family: SimSun, Arial, sans-serif;
|
||||
font-size: 9pt;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
table {
|
||||
margin: 3px;
|
||||
border: 1px solid #000;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table, th, td {
|
||||
|
|
@ -35,25 +32,32 @@
|
|||
}
|
||||
.div-with-border {
|
||||
border-bottom: 1px solid #000;
|
||||
padding: 5px;
|
||||
width: 200px;
|
||||
padding: 1mm;
|
||||
width: 37mm;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.qrcode {
|
||||
width: 18mm;
|
||||
height: 18mm;
|
||||
margin-top: 2mm;
|
||||
margin-bottom: 2mm;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table th:each="item, iterStat : ${list}" th:style="${iterStat.index == 0} ? 'page-break-before: auto;' : 'page-break-before: always;'">
|
||||
<tr>
|
||||
<td style="width: 150px;text-align: center;padding: 5px;">
|
||||
<img height="120" th:src="${item.qrCode}" width="120"/>
|
||||
<div th:text="${item.printNo}">20250227100950-0</div>
|
||||
<td style="width: 20mm;text-align: center;">
|
||||
<img alt="" class="qrcode" th:src="${item.qrCode}"/>
|
||||
<div th:text="${item.printLabel}">20250227100950-0</div>
|
||||
</td>
|
||||
<td style="width: 200px;text-align: left;vertical-align: top">
|
||||
<div class="title div-with-border"><img alt="logo" height="20" src="../../img/logo2.png" style="margin-right: 5px;" /></div>
|
||||
<td style="text-align: left;vertical-align: top">
|
||||
<div class="title div-with-border"><img alt="logo" style="height: 5mm" src="../../img/logo2.png"/></div>
|
||||
<div class="div-with-border">SAP编码: <span th:text="${item.materialNo}"></span></div>
|
||||
<div class="div-with-border">名称: <span th:text="${item.materialDesc}"></span></div>
|
||||
<div class="div-with-border" style="height: 8mm">名称: <span th:text="${item.materialDesc}"></span></div>
|
||||
<div class="div-with-border">数量: <span th:text="${item.printNum}"></span></div>
|
||||
<div style="padding: 5px;">批次号: <span th:text="${item.batchNo}"></span></div>
|
||||
<div style="padding: 1mm;">批次号: <span th:text="${item.batchNo}"></span></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
|||
|
|
@ -5,44 +5,58 @@
|
|||
<title>齐套标签</title>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<style>
|
||||
@media print {
|
||||
body {
|
||||
font-size: 10pt;
|
||||
}
|
||||
@page {
|
||||
size: 60mm 40mm;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
width: 58mm;
|
||||
height: 38mm;
|
||||
font-size: 8pt;
|
||||
font-family: SimSun, Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 10pt;
|
||||
padding-left: 1mm;
|
||||
padding-top: 1mm;
|
||||
line-height: 1.1;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
-webkit-print-color-adjust: exact;
|
||||
print-color-adjust: exact;
|
||||
}
|
||||
|
||||
table {
|
||||
margin: 3px;
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
|
||||
th, td {
|
||||
border: 1px solid #000;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.qrcode {
|
||||
width: 18mm;
|
||||
height: 18mm;
|
||||
margin-top: 2mm;
|
||||
margin-bottom: 2mm;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<tr style="height: 50px;">
|
||||
<tr style="height: 12mm;">
|
||||
<td colspan="3" th:text="${info.packageDesc}">
|
||||
左踏板连接架
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="4" style="text-align: center;width: 100px;">
|
||||
<img alt="" height="100" th:src="${info.qrCode}"/>
|
||||
<td rowspan="4" style="text-align: center;">
|
||||
<img class="qrcode" alt="" th:src="${info.qrCode}"/>
|
||||
</td>
|
||||
<td style="width: 70px;">
|
||||
<td style="width: 13mm;">
|
||||
采购单号:
|
||||
</td>
|
||||
<td style="width: 100px;" th:text="${info.externalOrderNo}">
|
||||
<td style="width: 23mm;" th:text="${info.externalOrderNo}">
|
||||
S2507090053
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -4,44 +4,93 @@
|
|||
<meta charset="UTF-8"/>
|
||||
<title>钢构件物料标签</title>
|
||||
<style>
|
||||
@page {
|
||||
size: 60mm 40mm;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 9pt;
|
||||
width: 58mm;
|
||||
height: 38mm;
|
||||
font-size: 8pt;
|
||||
font-family: SimSun, Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding-left: 1mm;
|
||||
padding-top: 1mm;
|
||||
line-height: 1.1;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
-webkit-print-color-adjust: exact;
|
||||
print-color-adjust: exact;
|
||||
}
|
||||
table, th, td {
|
||||
border: 1px solid black;
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
padding: 5px;
|
||||
text-align: left;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
|
||||
tr td {
|
||||
border: 1px solid #000;
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 34mm;
|
||||
}
|
||||
|
||||
.qrcode {
|
||||
width: 18mm;
|
||||
height: 18mm;
|
||||
margin-top: 2mm;
|
||||
margin-bottom: 2mm;
|
||||
}
|
||||
|
||||
.name {
|
||||
height: 8mm;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table th:each="item , iterStat: ${list}" th:style="${iterStat.index == 0} ? 'page-break-before: auto;' : 'page-break-before: always;'">
|
||||
<tr>
|
||||
<td colspan="4" th:text="|${item.materialDesc}(${info.supplierCode})|">833-33-07-NF左踏板连接架(0000101627)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" rowspan="3">
|
||||
<img alt="" height="130" th:src="${item.qrCodeImage}" width="130"/>
|
||||
</td>
|
||||
<td colspan="2" th:text="${item.drawingNo}">833-33-07-NF</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 70px;"><span style="font-weight: bold">SAP编码:</span></td>
|
||||
<td th:text="${item.materialNo}">2100080450</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" rowspan="3">
|
||||
<img alt="" height="100" th:src="${item.image}"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr></tr>
|
||||
<tr>
|
||||
<td colspan="2" style="height: 20px;font-size: 6pt;" th:text="${item.qrCode}">77777</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div th:each="item , iterStat: ${list}"
|
||||
th:style="${iterStat.index == 0} ? 'page-break-before: auto;' : 'page-break-before: always;'">
|
||||
<div th:text="${index}">1</div>
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<div th:text="|${item.materialDesc}(${info.supplierCode})|" class="name">
|
||||
833-33-07-NF左踏板连接架(0000101627)833-33-07-NF左踏板连接架NF左踏板连接架NF左踏板连接架(0000101627)
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" rowspan="3" style="text-align: center">
|
||||
<img th:src="${item.qrCodeImage}" class="qrcode"
|
||||
src="https://img-s.msn.cn/tenant/amp/entityid/AA1RXD8a.img" alt=""/>
|
||||
</td>
|
||||
<td colspan="2" th:text="${item.drawingNo}">833-33-07-NF</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold;text-align: center;font-size: 7pt;width: 10mm">SAP编码</td>
|
||||
<td th:text="${item.materialNo}" style="width: 20mm">2100080450</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" rowspan="2" class="center">
|
||||
<img th:src="${item.image}" class="img" src="https://img-s.msn.cn/tenant/amp/entityid/AA1RVn7C.img"
|
||||
alt=""/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" style="font-size: 6pt;text-align: center;height: 2mm" th:text="${item.qrCodeId}">
|
||||
1244565616465_1
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,16 +5,18 @@
|
|||
<title>托盘标签</title>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<style>
|
||||
@media print {
|
||||
body {
|
||||
font-size: 10pt;
|
||||
}
|
||||
@page {
|
||||
size: 60mm 40mm;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
width: 58mm;
|
||||
height: 38mm;
|
||||
font-size: 8pt;
|
||||
font-family: SimSun, Arial, sans-serif;
|
||||
margin: 3px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 10pt;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
|
|
@ -23,25 +25,31 @@
|
|||
|
||||
th, td {
|
||||
border: 1px solid #000;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.qrcode {
|
||||
width: 18mm;
|
||||
height: 18mm;
|
||||
margin-top: 2mm;
|
||||
margin-bottom: 2mm;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<tr style="height: 50px;">
|
||||
<tr style="height: 12mm;">
|
||||
<td colspan="3" th:text="${info.packageDesc}">
|
||||
左踏板连接架
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="3" style="text-align: center;width: 100px;">
|
||||
<img alt="" height="100" th:src="${info.qrCode}"/>
|
||||
<td rowspan="3" style="text-align: center;">
|
||||
<img class="qrcode" alt="" th:src="${info.qrCode}"/>
|
||||
</td>
|
||||
<td style="width: 60px;">
|
||||
<td style="width: 13mm;">
|
||||
托盘号:
|
||||
</td>
|
||||
<td style="width: 100px;" th:text="${info.trayNo}">
|
||||
<td style="width: 23mm;" th:text="${info.trayNo}">
|
||||
S2507090053
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -6,26 +6,23 @@
|
|||
<title>二维码</title>
|
||||
<style>
|
||||
@page {
|
||||
size: A4 landscape; /* 横向 A4 */
|
||||
margin: 0; /* 页边距 */
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: SimSun, serif;
|
||||
font-size: 12px;
|
||||
margin: 10px;
|
||||
size: 40mm 60mm;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.qrcode {
|
||||
width: 100px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.qrcode img {
|
||||
width: 100%;
|
||||
margin-top: 1mm;
|
||||
width: 35mm;
|
||||
height: 35mm;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 38mm;
|
||||
height: 58mm;
|
||||
font-size: 10pt;
|
||||
font-family: SimSun, serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
page-break-after: always;
|
||||
}
|
||||
|
||||
|
|
@ -36,8 +33,11 @@
|
|||
</head>
|
||||
<body>
|
||||
<div class="container" th:each="item : ${datas}">
|
||||
<div class="qrcode"><img alt="" th:src="${item.qrCode}" src="../img/qrcode.png"/>
|
||||
<span th:text="${item.no}">ICO2156115651</span>
|
||||
<div style="text-align: center">
|
||||
<div>
|
||||
<img class="qrcode" alt="" th:src="${item.qrCode}" src="../img/qrcode.png"/>
|
||||
</div>
|
||||
<div th:text="${item.no}">ICO2156115651</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -104,6 +104,11 @@ public class DeliverNormalOrderItemDTO {
|
|||
*/
|
||||
private String printNo;
|
||||
|
||||
/**
|
||||
* 打印名称
|
||||
*/
|
||||
private String printLabel;
|
||||
|
||||
/**
|
||||
* 二维码base64
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -114,4 +114,9 @@ public class DeliverStructuralPackageOrderTrayItemVO implements Serializable {
|
|||
* 二维码内容
|
||||
*/
|
||||
private String qrCode;
|
||||
|
||||
/**
|
||||
* 二维码id
|
||||
*/
|
||||
private String qrCodeId;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue