|
|
@@ -21,12 +21,16 @@ import java.awt.print.PrinterJob;
|
|
|
import java.io.BufferedReader;
|
|
|
import java.io.InputStream;
|
|
|
import java.io.InputStreamReader;
|
|
|
+import java.util.ArrayList;
|
|
|
import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Locale;
|
|
|
import java.util.Map;
|
|
|
import java.util.Properties;
|
|
|
|
|
|
/**
|
|
|
* 标签打印工具:第一行二维码,第二行工件码文本
|
|
|
+ * 自动跳过 PDF/XPS 等虚拟打印机,直接发送到实体打印机
|
|
|
*/
|
|
|
public class PrintUtil {
|
|
|
|
|
|
@@ -37,6 +41,22 @@ public class PrintUtil {
|
|
|
/** 标签高度(毫米) */
|
|
|
private static final double LABEL_HEIGHT_MM = 40;
|
|
|
|
|
|
+ /** 虚拟打印机关键词(这些会弹另存为对话框,不可用) */
|
|
|
+ private static final String[] VIRTUAL_PRINTER_KEYWORDS = {
|
|
|
+ "microsoft print to pdf",
|
|
|
+ "microsoft xps",
|
|
|
+ "onenote",
|
|
|
+ "fax",
|
|
|
+ "传真",
|
|
|
+ "send to onenote",
|
|
|
+ "adobe pdf",
|
|
|
+ "foxit",
|
|
|
+ "pdf creator",
|
|
|
+ "bullzip",
|
|
|
+ "doPDF",
|
|
|
+ "cutePDF"
|
|
|
+ };
|
|
|
+
|
|
|
/**
|
|
|
* 打印工件标签
|
|
|
*
|
|
|
@@ -50,17 +70,16 @@ public class PrintUtil {
|
|
|
}
|
|
|
String content = sn.trim();
|
|
|
try {
|
|
|
- PrinterJob job = PrinterJob.getPrinterJob();
|
|
|
PrintService printService = findPrintService();
|
|
|
if (printService == null) {
|
|
|
- log.error("未找到可用打印机");
|
|
|
+ log.error("未找到可用实体打印机,请在 config.properties 中配置 mes.printer_name");
|
|
|
return false;
|
|
|
}
|
|
|
+
|
|
|
+ PrinterJob job = PrinterJob.getPrinterJob();
|
|
|
job.setPrintService(printService);
|
|
|
|
|
|
BufferedImage qrImage = generateQrCode(content, 200);
|
|
|
- job.setPrintable(new LabelPrintable(qrImage, content));
|
|
|
- job.setJobName("MES标签-" + content);
|
|
|
|
|
|
PageFormat pageFormat = job.defaultPage();
|
|
|
Paper paper = new Paper();
|
|
|
@@ -69,9 +88,12 @@ public class PrintUtil {
|
|
|
paper.setSize(width, height);
|
|
|
paper.setImageableArea(5, 5, width - 10, height - 10);
|
|
|
pageFormat.setPaper(paper);
|
|
|
- job.setPrintable(new LabelPrintable(qrImage, content), pageFormat);
|
|
|
|
|
|
+ // 静默打印,不弹打印对话框
|
|
|
+ job.setPrintable(new LabelPrintable(qrImage, content), pageFormat);
|
|
|
+ job.setJobName("MES标签-" + content);
|
|
|
job.print(new HashPrintRequestAttributeSet());
|
|
|
+
|
|
|
log.info("打印成功: sn={}, printer={}", content, printService.getName());
|
|
|
return true;
|
|
|
} catch (PrinterException e) {
|
|
|
@@ -96,33 +118,90 @@ public class PrintUtil {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 查找打印机:优先使用配置文件指定名称,否则使用系统默认打印机
|
|
|
+ * 查找打印机:
|
|
|
+ * 1. 优先匹配配置项 mes.printer_name
|
|
|
+ * 2. 其次使用系统默认打印机(但排除虚拟打印机)
|
|
|
+ * 3. 再从全部打印机中找第一台实体打印机
|
|
|
*/
|
|
|
private static PrintService findPrintService() {
|
|
|
try {
|
|
|
- String printerName = readPrinterName();
|
|
|
PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null);
|
|
|
+ if (services == null || services.length == 0) {
|
|
|
+ log.error("系统中未发现任何打印机");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 打印日志,方便排查
|
|
|
+ List<String> allNames = new ArrayList<>();
|
|
|
+ List<String> physicalNames = new ArrayList<>();
|
|
|
+ for (PrintService service : services) {
|
|
|
+ String name = service.getName();
|
|
|
+ allNames.add(name);
|
|
|
+ if (!isVirtualPrinter(name)) {
|
|
|
+ physicalNames.add(name);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ log.info("系统打印机列表: {}", allNames);
|
|
|
+ log.info("可用实体打印机: {}", physicalNames);
|
|
|
+
|
|
|
+ // 1. 配置文件指定名称
|
|
|
+ String printerName = readPrinterName();
|
|
|
if (printerName != null && !printerName.trim().isEmpty()) {
|
|
|
+ String key = printerName.trim();
|
|
|
for (PrintService service : services) {
|
|
|
- if (service.getName().contains(printerName.trim())) {
|
|
|
- return service;
|
|
|
+ if (service.getName().toLowerCase(Locale.ROOT).contains(key.toLowerCase(Locale.ROOT))) {
|
|
|
+ if (isVirtualPrinter(service.getName())) {
|
|
|
+ log.warn("配置的打印机[{}]是虚拟打印机,请改成实体打印机名称", service.getName());
|
|
|
+ } else {
|
|
|
+ log.info("使用配置打印机: {}", service.getName());
|
|
|
+ return service;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- log.warn("未找到配置的打印机[{}],尝试使用默认打印机", printerName);
|
|
|
+ log.warn("未找到配置的打印机[{}],继续自动选择实体打印机", key);
|
|
|
}
|
|
|
+
|
|
|
+ // 2. 系统默认打印机(排除虚拟)
|
|
|
PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();
|
|
|
- if (defaultService != null) {
|
|
|
+ if (defaultService != null && !isVirtualPrinter(defaultService.getName())) {
|
|
|
+ log.info("使用系统默认打印机: {}", defaultService.getName());
|
|
|
return defaultService;
|
|
|
}
|
|
|
- if (services.length > 0) {
|
|
|
- return services[0];
|
|
|
+ if (defaultService != null) {
|
|
|
+ log.warn("系统默认打印机是虚拟打印机[{}],已跳过", defaultService.getName());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 自动选择第一台实体打印机
|
|
|
+ for (PrintService service : services) {
|
|
|
+ if (!isVirtualPrinter(service.getName())) {
|
|
|
+ log.info("自动选择实体打印机: {}", service.getName());
|
|
|
+ return service;
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ log.error("未找到实体打印机,系统默认可能是 Microsoft Print to PDF");
|
|
|
} catch (Exception e) {
|
|
|
log.error("查找打印机异常: {}", e.getMessage());
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 判断是否为虚拟打印机(会弹另存为对话框)
|
|
|
+ */
|
|
|
+ private static boolean isVirtualPrinter(String name) {
|
|
|
+ if (name == null) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ String lower = name.toLowerCase(Locale.ROOT);
|
|
|
+ for (String keyword : VIRTUAL_PRINTER_KEYWORDS) {
|
|
|
+ if (lower.contains(keyword.toLowerCase(Locale.ROOT))) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
private static String readPrinterName() {
|
|
|
try {
|
|
|
InputStream is = ClassLoader.getSystemResourceAsStream("config/config.properties");
|