package com.gaotao.modules.base.task; import com.gaotao.modules.base.entity.PrintTask; import com.gaotao.modules.base.service.PrintTaskService; import com.google.gson.Gson; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.io.OutputStream; import java.net.Socket; import java.util.List; import java.util.Map; /** * 打印任务定时调度器 * *

功能说明:

* * *

并发控制:

* */ @Slf4j @Component public class PrintTaskScheduler { @Autowired private PrintTaskService printTaskService; private static final Gson gson = new Gson(); @Value("${dashboard.push.enabled:true}") private boolean dashboardPushEnabled; // 每秒执行一次 @Scheduled(fixedDelay = 500) public void processPrintTasks() { try { // 1. 获取待执行的任务(每次处理10个) List pendingTasks = printTaskService.getPendingTasks(10); if (pendingTasks.isEmpty()) { return; // 没有待处理任务 } log.info("【打印队列】发现 {} 个待执行任务", pendingTasks.size()); // 2. 按FIFO顺序逐个执行 for (PrintTask task : pendingTasks) { processTask(task); } } catch (Exception e) { log.error("打印任务调度器执行异常: {}", e.getMessage(), e); } } /** * 处理单个打印任务 */ private void processTask(PrintTask task) { Long taskId = task.getId(); String printerIp = task.getPrinterIp(); try { // 1. 标记为执行中(乐观锁,防止并发重复执行) boolean marked = printTaskService.markAsProcessing(taskId); if (!marked) { log.debug("任务 {} 已被其他线程处理,跳过", taskId); return; } log.info("【打印队列】开始执行任务 taskId={}, 打印机={}, 份数={}", taskId, printerIp, task.getCopies()); // 2. 解析标签数据 Map labelData = null; if (task.getLabelData() != null && !task.getLabelData().trim().isEmpty()) { labelData = gson.fromJson(task.getLabelData(), Map.class); } // 3. 执行打印 boolean success = executePrint( printerIp, task.getZplCode(), task.getCopies(), task.getRfidFlag(), labelData ); // 4. 更新任务状态 if (success) { printTaskService.markAsSuccess(taskId); log.info("【打印队列】✓ 任务完成 taskId={}, 打印机={}", taskId, printerIp); } else { printTaskService.markAsFailed(taskId, "打印失败,未返回成功标识"); log.error("【打印队列】✗ 任务失败 taskId={}, 打印机={}", taskId, printerIp); } } catch (Exception e) { log.error("【打印队列】✗ 任务执行异常 taskId={}, 错误: {}", taskId, e.getMessage(), e); printTaskService.markAsFailed(taskId, "执行异常: " + e.getMessage()); } } /** * 执行打印(发送ZPL到打印机) * 注意:ZPL代码已在入队时组装好(包括RFID指令),这里只需要直接发送 * * @param printerIp 打印机IP * @param zplCode ZPL代码(已包含RFID指令) * @param copies 打印份数 * @param rfidFlag RFID标识(用于日志) * @param labelData 标签数据(未使用,保留以备后续扩展) * @return 是否成功 */ private boolean executePrint(String printerIp, String zplCode, Integer copies, String rfidFlag, Map labelData) { Socket socket = null; try { // 1. 连接打印机 socket = new Socket(printerIp, 9100); socket.setSoTimeout(10000); // 10秒超时 OutputStream os = socket.getOutputStream(); int actualCopies = copies != null && copies > 0 ? copies : 1; // 2. 直接发送ZPL代码(已在入队时组装好,包括RFID指令) log.debug("开始发送ZPL到打印机 {}, 份数: {}, RFID: {}", printerIp, actualCopies, rfidFlag); for (int i = 0; i < actualCopies; i++) { os.write(zplCode.getBytes("UTF-8")); os.flush(); // RFID标签需要等待处理时间 if ("Y".equals(rfidFlag)) { Thread.sleep(1000); // RFID标签等待1秒 log.debug("RFID标签打印完成 {} / {}", i + 1, actualCopies); } } log.debug("✓ ZPL已发送到打印机 {}, 份数: {}", printerIp, actualCopies); return true; } catch (Exception e) { log.error("发送ZPL到打印机失败: printerIp={}, error={}", printerIp, e.getMessage(), e); return false; } finally { if (socket != null) { try { socket.close(); } catch (Exception e) { log.warn("关闭socket失败: {}", e.getMessage()); } } } } }