打印问题
This commit is contained in:
@@ -12,7 +12,6 @@ import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
@@ -61,7 +60,7 @@ public class PrintMqListener {
|
||||
}
|
||||
Boolean printOrder = jsonObject.getBoolean("printOrder");
|
||||
funUtil.runFunAndCheckKey(() -> {
|
||||
printerHandler.handler(orderId, printOrder != null && !printOrder ? PrinterHandler.PrintTypeEnum.ONE : PrinterHandler.PrintTypeEnum.ONE_AND_ORDER, null);
|
||||
printerHandler.handler(orderId, printOrder != null && !printOrder ? PrinterHandler.PrintTypeEnum.ONE : PrinterHandler.PrintTypeEnum.ONE_AND_ORDER);
|
||||
return null;
|
||||
}, RedisCst.getLockKey("orderPrint", orderId));
|
||||
});
|
||||
@@ -72,7 +71,7 @@ public class PrintMqListener {
|
||||
*/
|
||||
@RabbitListener(queues = {"${spring.profiles.active}-" + RabbitConstants.Queue.ORDER_HANDOVER_PRINT_QUEUE})
|
||||
public void handoverPrint(String id) {
|
||||
invokeFun("handoverPrint", "java.order", id, (data) -> printerHandler.handler(data, PrinterHandler.PrintTypeEnum.HANDOVER, null));
|
||||
invokeFun("handoverPrint", "java.order", id, (data) -> printerHandler.handler(data, PrinterHandler.PrintTypeEnum.HANDOVER));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,6 +79,6 @@ public class PrintMqListener {
|
||||
*/
|
||||
@RabbitListener(queues = {"${spring.profiles.active}-" + RabbitConstants.Queue.CALL_TABLE_PRINT_QUEUE})
|
||||
public void callTablePrint(String id) {
|
||||
invokeFun("handoverPrint", "java.order", id, (data) -> printerHandler.handler(data, PrinterHandler.PrintTypeEnum.CALL, null));
|
||||
invokeFun("handoverPrint", "java.order", id, (data) -> printerHandler.handler(data, PrinterHandler.PrintTypeEnum.CALL));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,5 @@ public class OrderInfoPrintDTO implements Serializable {
|
||||
*/
|
||||
@NotNull(message = "打印类型不为空")
|
||||
private Integer type;
|
||||
/**
|
||||
* 打印机id
|
||||
*/
|
||||
private Long machineId;
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,6 @@ import com.czg.order.entity.PrintMachineLog;
|
||||
* @since 2025-03-11
|
||||
*/
|
||||
public interface PrintMachineLogService extends IService<PrintMachineLog> {
|
||||
void save(PrintMachine config, String bizType, String printContent, Object respJson);
|
||||
void save(PrintMachine config, String bizType, String printContent, String respJson);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
package com.czg.service.order.print;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.text.UnicodeUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.czg.account.dto.HandoverRecordDTO;
|
||||
import com.czg.account.entity.HandoverRecord;
|
||||
import com.czg.account.entity.PrintMachine;
|
||||
import com.czg.account.entity.ShopInfo;
|
||||
import com.czg.account.service.ShopInfoService;
|
||||
import com.czg.order.entity.OrderDetail;
|
||||
import com.czg.order.entity.OrderInfo;
|
||||
import com.czg.service.order.enums.OrderStatusEnums;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.springframework.http.HttpEntity;
|
||||
@@ -20,12 +21,13 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Administrator
|
||||
@@ -33,11 +35,6 @@ import java.util.List;
|
||||
@Component
|
||||
@Slf4j
|
||||
public class FeiPrinter extends PrinterHandler implements PrinterImpl {
|
||||
@Resource
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Resource
|
||||
private ShopInfoService shopInfoService;
|
||||
|
||||
// API 地址
|
||||
private static final String URL = "http://api.feieyun.cn/Api/Open/";
|
||||
@@ -72,10 +69,8 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
|
||||
String remark = orderDetail.getRemark();
|
||||
String content = buildDishPrintData(false, getPickupNum(orderInfo), orderInfo.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
|
||||
orderDetail.getProductName(), orderDetail.getSkuName(), orderDetail.getNum(), remark, orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
|
||||
Object o = sendPrintRequest(machine.getAddress(), content, null, "1");
|
||||
String o = sendPrintRequest(machine.getAddress(), content, null, "1");
|
||||
printMachineLogService.save(machine, "新订单", content, o);
|
||||
|
||||
// printMachineLogService.save(machine, "新订单", , );
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +79,7 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
|
||||
String remark = orderDetail.getRemark();
|
||||
String content = buildDishPrintData(true, getPickupNum(orderInfo), orderInfo.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
|
||||
orderDetail.getProductName(), orderDetail.getSkuName(), orderDetail.getReturnNum(), remark, orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
|
||||
Object o = sendPrintRequest(machine.getAddress(), content, null, "1");
|
||||
String o = sendPrintRequest(machine.getAddress(), content, null, "1");
|
||||
printMachineLogService.save(machine, "退款单", content, o);
|
||||
|
||||
}
|
||||
@@ -106,8 +101,8 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
|
||||
.setRemark(orderInfo.getRemark())
|
||||
.setDiscountAmount(orderInfo.getOriginAmount().subtract(orderInfo.getPayAmount()).toPlainString());
|
||||
String string = buildOrderPrintData(printInfoDTO, detailList);
|
||||
Object o = sendPrintRequest(machine.getAddress(), string, null, printerNum);
|
||||
printMachineLogService.save(machine, "退款单", string, o);
|
||||
String o = sendPrintRequest(machine.getAddress(), string, null, printerNum);
|
||||
printMachineLogService.save(machine, "结算单", string, o);
|
||||
|
||||
}
|
||||
|
||||
@@ -143,7 +138,7 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
|
||||
}
|
||||
|
||||
String string = buildOrderPrintData(printInfoDTO, detailList);
|
||||
Object resp = sendPrintRequest(machine.getAddress(), string, null, printerNum);
|
||||
String resp = sendPrintRequest(machine.getAddress(), string, null, printerNum);
|
||||
printMachineLogService.save(machine, "结算单", string, resp);
|
||||
}
|
||||
|
||||
@@ -151,7 +146,7 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
|
||||
protected void callNumPrint(PrintMachine machine, String callNum, String shopName, String tableName, String tableNote, String preNum, String codeUrl, LocalDateTime takeTime, String shopNote) {
|
||||
String voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一条新的排号记录\"}";
|
||||
String data = buildCallTicketData(shopName, tableName, callNum, preNum, codeUrl, shopNote, takeTime);
|
||||
Object resp = sendPrintRequest(machine.getAddress(), data, voiceJson, "1");
|
||||
String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, "1");
|
||||
printMachineLogService.save(machine, "叫号单", data, resp);
|
||||
}
|
||||
|
||||
@@ -170,7 +165,7 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R sendPrintRequest(String address, String metaPrintData, String voiceData, String printerNum) {
|
||||
public String sendPrintRequest(String address, String metaPrintData, String voiceData, String printerNum) {
|
||||
log.info("飞蛾打印机开始发送打印请求, 设备地址: {}, 元数据: {}", address, metaPrintData);
|
||||
String time = String.valueOf(System.currentTimeMillis() / 1000);
|
||||
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
|
||||
@@ -189,12 +184,68 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
|
||||
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
|
||||
|
||||
String result = restTemplate.postForObject(URL, requestEntity, String.class);
|
||||
log.info("打印结果: {}", result);
|
||||
return (R) result;
|
||||
log.info("飞鹅打印结果: {}", result);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
log.error("打印请求失败: {}", e.getMessage());
|
||||
throw new RuntimeException("飞蛾打印请求失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查飞鹅打印机 打印任务是否已打印
|
||||
*
|
||||
* @param printOrderId 打印订单编号
|
||||
* @return null-未知错误,true-已打印,false-未打印
|
||||
*/
|
||||
public Boolean checkFPrintStatus(String printOrderId) {
|
||||
String time = String.valueOf(System.currentTimeMillis() / 1000);
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
paramMap.put("user", USER);
|
||||
paramMap.put("stime", time);
|
||||
paramMap.put("sig", signature(time));
|
||||
paramMap.put("apiname", "Open_queryOrderState");
|
||||
paramMap.put("orderid", printOrderId);
|
||||
Boolean ret;
|
||||
try {
|
||||
String resp = HttpUtil.post(URL, paramMap, 1000 * 5);
|
||||
//成功 {"msg":"ok","ret":0,"data":true,"serverExecutedTime":4}
|
||||
//失败 {"msg":"ok","ret":0,"data":false,"serverExecutedTime":4}
|
||||
JSONObject json = JSONUtil.parseObj(UnicodeUtil.toString(resp));
|
||||
log.info("飞鹅打印机 打印任务状态响应: {}", json);
|
||||
ret = json.getBool("data");
|
||||
} catch (Exception e) {
|
||||
ret = null;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查飞鹅打印机是否在线
|
||||
*
|
||||
* @param sn 设备编号
|
||||
* @return 在线,工作状态正常。/离线。/未知错误
|
||||
*/
|
||||
public String checkOnline(String sn) {
|
||||
String time = String.valueOf(System.currentTimeMillis() / 1000);
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
paramMap.put("user", USER);
|
||||
paramMap.put("stime", time);
|
||||
paramMap.put("sig", signature(time));
|
||||
paramMap.put("apiname", "Open_queryPrinterStatus");
|
||||
paramMap.put("sn", sn);
|
||||
String msg;
|
||||
try {
|
||||
String resp = HttpUtil.post(URL, paramMap, 1000 * 5);
|
||||
//成功 开机 {"msg":"ok","ret":0,"data":"在线,工作状态正常。","serverExecutedTime":4}
|
||||
//成功 离线 {"msg":"ok","ret":0,"data":"离线。","serverExecutedTime":7}
|
||||
JSONObject json = JSONUtil.parseObj(UnicodeUtil.toString(resp));
|
||||
log.info("飞鹅打印机状态响应: {}", json);
|
||||
msg = json.getStr("data");
|
||||
} catch (Exception e) {
|
||||
msg = "未知错误";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import lombok.ToString;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -50,6 +51,8 @@ public abstract class PrinterHandler {
|
||||
protected PrinterHandler nextPrinter;
|
||||
protected String printerBrand;
|
||||
|
||||
@Resource
|
||||
protected RestTemplate restTemplate;
|
||||
@Resource
|
||||
protected OrderDetailService orderDetailService;
|
||||
@Resource
|
||||
@@ -81,7 +84,11 @@ public abstract class PrinterHandler {
|
||||
@Getter
|
||||
public enum PrintTypeEnum {
|
||||
HANDOVER("交班", "handover"),
|
||||
ORDER("订单", "order"), ONE("菜品", "one"), CALL("叫号", "call"), ONE_AND_ORDER("菜品和结算单同时打印", "oneAndOrder"), PRE_ORDER("预结算单", "preOrder");
|
||||
ORDER("订单", "order"),
|
||||
ONE("菜品", "one"),
|
||||
CALL("叫号", "call"),
|
||||
ONE_AND_ORDER("菜品和结算单同时打印", "oneAndOrder"),
|
||||
PRE_ORDER("预结算单", "preOrder");
|
||||
private final String name;
|
||||
private final String code;
|
||||
|
||||
@@ -145,10 +152,9 @@ public abstract class PrinterHandler {
|
||||
* @param printType 打印类型,JSON数组 refund-确认退款单 handover-交班单 queue-排队取号
|
||||
* @return 打印机列表
|
||||
*/
|
||||
private List<PrintMachine> getPrintMachine(Long shopId, String subType, String printMethod, String printType, Long machineId) {
|
||||
private List<PrintMachine> getPrintMachine(Long shopId, String subType, String printMethod, String printType) {
|
||||
QueryWrapper wrapper = new QueryWrapper()
|
||||
.eq(PrintMachine::getStatus, 1)
|
||||
.eq(PrintMachine::getId, machineId)
|
||||
.eq(PrintMachine::getShopId, shopId)
|
||||
.eq(PrintMachine::getSubType, subType)
|
||||
.eq(PrintMachine::getConnectionType, "网络");
|
||||
@@ -171,10 +177,6 @@ public abstract class PrinterHandler {
|
||||
wrapper.like(PrintMachine::getPrintType, printType);
|
||||
}
|
||||
List<PrintMachine> list = printMachineService.list(wrapper);
|
||||
// for (PrintMachine item : list) {
|
||||
// //实际打印以传递的参数为准
|
||||
// item.setPrintMethod(printMethod);
|
||||
// }
|
||||
if (list.isEmpty()) {
|
||||
log.error("店铺未配置打印机,店铺id: {}", shopId);
|
||||
return list;
|
||||
@@ -190,7 +192,7 @@ public abstract class PrinterHandler {
|
||||
* @param data 传递的数据
|
||||
* @param printTypeEnum order returnOrder preOrder one call handover
|
||||
*/
|
||||
public void handler(String data, PrintTypeEnum printTypeEnum, Long machineId) {
|
||||
public void handler(String data, PrintTypeEnum printTypeEnum) {
|
||||
Long shopId;
|
||||
String printMethod = "";
|
||||
String printType = "";
|
||||
@@ -261,7 +263,7 @@ public abstract class PrinterHandler {
|
||||
}
|
||||
|
||||
Object finalObj = obj;
|
||||
getPrintMachine(shopId, "cash", printMethod, printType, machineId).forEach(machine -> {
|
||||
getPrintMachine(shopId, "cash", printMethod, printType).forEach(machine -> {
|
||||
handleRequest(machine, finalObj, printTypeEnum);
|
||||
// printPlaceTicket(isReturn, machine, orderInfo, shopInfo);
|
||||
});
|
||||
@@ -447,17 +449,7 @@ public abstract class PrinterHandler {
|
||||
log.info("台位费商品,不打印");
|
||||
return;
|
||||
}
|
||||
// ProdSku sku = prodSkuService.getById(item.getSkuId());
|
||||
// if (isTemporary == 0 && sku == null) {
|
||||
// log.error("商品不存在, id: {}", item.getSkuId());
|
||||
// return;
|
||||
// } else if (isTemporary == 1) {
|
||||
// sku = new ProdSku();
|
||||
// }
|
||||
|
||||
|
||||
// String remark = StrUtil.isNotBlank(sku.getSpecInfo()) ? sku.getSpecInfo() : "";
|
||||
// item.setRemark(remark);
|
||||
if (item.getReturnNum().compareTo(BigDecimal.ZERO) > 0) {
|
||||
returnDishesPrint(orderInfo, item, machine);
|
||||
}
|
||||
@@ -468,7 +460,8 @@ public abstract class PrinterHandler {
|
||||
|
||||
// 保存已打印信息
|
||||
OrderDetail orderDetail = detailMap.get(item.getId());
|
||||
redisService.set(RedisCst.getPrintOrderDetailKey(orderInfo.getId(), item.getId()), JSONObject.toJSONString(new PrintDetailInfo().setPrint(item.getIsPrint() == 1).setDetailId(item.getId())
|
||||
redisService.set(RedisCst.getPrintOrderDetailKey(orderInfo.getId(), item.getId()),
|
||||
JSONObject.toJSONString(new PrintDetailInfo().setPrint(item.getIsPrint() == 1).setDetailId(item.getId())
|
||||
.setPrintNum(orderDetail.getNum()).setPrintReturnNum(orderDetail.getReturnNum())), 3600 * 24);
|
||||
|
||||
});
|
||||
|
||||
@@ -9,7 +9,6 @@ import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.account.dto.HandoverRecordDTO;
|
||||
import com.czg.account.entity.HandoverRecord;
|
||||
import com.czg.order.entity.OrderDetail;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
@@ -69,10 +68,9 @@ public interface PrinterImpl {
|
||||
* @param metaPrintData 打印元数据
|
||||
* @param voiceData 语音信息
|
||||
* @param printNum 打印联数
|
||||
* @param <R> 返回数据类型
|
||||
* @return 打印结果
|
||||
*/
|
||||
<R> R sendPrintRequest(String address, String metaPrintData, String voiceData, String printNum);
|
||||
String sendPrintRequest(String address, String metaPrintData, String voiceData, String printNum);
|
||||
|
||||
/**
|
||||
* 获取当前打印机标签信息
|
||||
@@ -560,12 +558,6 @@ public interface PrinterImpl {
|
||||
return str;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("水煮肉片".length());
|
||||
System.out.println(StrUtil.repeat(' ', 8));
|
||||
System.out.println(StrUtil.fillAfter("水煮肉片", ' ', 21));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取填充字符串, 并且换行
|
||||
*
|
||||
|
||||
@@ -4,11 +4,10 @@ import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.czg.account.dto.HandoverRecordDTO;
|
||||
import com.czg.account.entity.HandoverRecord;
|
||||
import com.czg.account.entity.PrintMachine;
|
||||
import com.czg.account.entity.ShopInfo;
|
||||
import com.czg.account.service.ShopInfoService;
|
||||
import com.czg.order.entity.OrderDetail;
|
||||
import com.czg.order.entity.OrderInfo;
|
||||
import com.czg.service.order.enums.OrderStatusEnums;
|
||||
@@ -20,9 +19,7 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
@@ -45,12 +42,6 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
||||
//APPSECRET
|
||||
private static final String APP_SECRET = "2022bsjZF544GAH";
|
||||
|
||||
@Resource
|
||||
private ShopInfoService shopInfoService;
|
||||
|
||||
@Resource
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
public YxyPrinter() {
|
||||
super("云想印");
|
||||
}
|
||||
@@ -75,7 +66,7 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
||||
|
||||
|
||||
@Override
|
||||
public <R> R sendPrintRequest(String address, String metaPrintData, String voiceData, String printNum) {
|
||||
public String sendPrintRequest(String address, String metaPrintData, String voiceData, String printNum) {
|
||||
log.info("开始请求云享印,请求数据:{}, {}", voiceData, metaPrintData);
|
||||
//设备名称
|
||||
//行为方式 1:只打印数据 2:只播放信息 3:打印数据并播放信息
|
||||
@@ -87,10 +78,9 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
||||
String time = String.valueOf(System.currentTimeMillis());
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
|
||||
Map<String, String> param = getToken(time, uuid);
|
||||
//参数
|
||||
MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
|
||||
multiValueMap.add("token", param.get("TOKEN"));
|
||||
multiValueMap.add("token", getToken(time, uuid));
|
||||
multiValueMap.add("devName", address);
|
||||
multiValueMap.add("actWay", 3);
|
||||
multiValueMap.add("cn", printNum);
|
||||
@@ -108,7 +98,7 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
||||
httpEntity, String.class);
|
||||
|
||||
log.info("请求云享印成功,响应数据: {}", httpResponse);
|
||||
return (R) httpResponse;
|
||||
return httpResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -116,9 +106,7 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
||||
String buildDishPrintData = buildDishPrintData(false, getPickupNum(orderInfo), DateUtil.format(orderDetail.getCreateTime(), "yyyy-MM-dd HH:mm:ss"), orderDetail.getProductName(), orderDetail.getSkuName(),
|
||||
orderDetail.getNum(), orderDetail.getRemark(), orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
|
||||
String voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}";
|
||||
// String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}";
|
||||
Object resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1");
|
||||
// sendPrintRequest(voiceJson, 3, 1, machine.getAddress(), data);
|
||||
String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1");
|
||||
printMachineLogService.save(machine, "新订单", buildDishPrintData, resp);
|
||||
|
||||
}
|
||||
@@ -127,9 +115,8 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
||||
protected void returnDishesPrint(OrderInfo orderInfo, OrderDetail orderDetail, PrintMachine machine) {
|
||||
String buildDishPrintData = buildDishPrintData(true, getPickupNum(orderInfo), DateUtil.format(orderDetail.getCreateTime(), "yyyy-MM-dd HH:mm:ss"), orderDetail.getProductName(), orderDetail.getSkuName(),
|
||||
orderDetail.getReturnNum(), orderDetail.getRemark(), orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
|
||||
// String voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}";
|
||||
String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}";
|
||||
Object resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1");
|
||||
String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1");
|
||||
printMachineLogService.save(machine, "退款单", buildDishPrintData, resp);
|
||||
|
||||
}
|
||||
@@ -141,18 +128,17 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
||||
.setOrderNo(orderInfo.getOrderNo()).setTradeDate(DateUtil.format(orderInfo.getCreateTime(), "yyyy-MM-dd HH:mm:ss")).setOperator("【POS-1】001").setPayAmount(orderInfo.getPayAmount().toPlainString())
|
||||
.setOriginalAmount(orderInfo.getOriginAmount().toPlainString()).setReturn(isReturn(orderInfo))
|
||||
.setBalance(balance).setPayType((ObjectUtil.isEmpty(orderInfo.getPayType()) || ObjectUtil.isNull(orderInfo.getPayType()) ? "" : orderInfo.getPayType())).setIntegral("0")
|
||||
.setOutNumber(orderInfo.getTakeCode()).setPrintTitle("结算单")
|
||||
.setOutNumber(orderInfo.getTakeCode()).setPrintTitle("退款单")
|
||||
.setRemark(orderInfo.getRemark()).setDiscountAmount(orderInfo.getOriginAmount().subtract(orderInfo.getPayAmount()).toPlainString());
|
||||
|
||||
String data = buildOrderPrintData(printInfoDTO, detailList);
|
||||
String voiceJson = "{\"PbizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}";
|
||||
// String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}";
|
||||
String printerNum = "1";
|
||||
if (StrUtil.isNotBlank(machine.getPrintQty())) {
|
||||
printerNum = machine.getPrintQty().split("\\^")[1];
|
||||
}
|
||||
String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, printerNum);
|
||||
printMachineLogService.save(machine, "新订单", data, resp);
|
||||
printMachineLogService.save(machine, "退款单", data, resp);
|
||||
|
||||
}
|
||||
|
||||
@@ -183,23 +169,28 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
||||
|
||||
String data = buildOrderPrintData(printInfoDTO, detailList);
|
||||
String voiceJson = "{\"PbizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}";
|
||||
// String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}";
|
||||
String printerNum = "1";
|
||||
if (StrUtil.isNotBlank(machine.getPrintQty())) {
|
||||
printerNum = machine.getPrintQty().split("\\^")[1];
|
||||
}
|
||||
String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, printerNum);
|
||||
// printMachineLogService.save(machine, printType, data, resp);
|
||||
printMachineLogService.save(machine, "新订单", data, resp);
|
||||
printMachineLogService.save(machine, "结算单", data, resp);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 叫号单打印
|
||||
*/
|
||||
@Override
|
||||
protected void callNumPrint(PrintMachine machine, String callNum, String shopName, String tableName, String tableNote, String preNum, String codeUrl, LocalDateTime takeTime, String shopNote) {
|
||||
String resp = buildCallTicketData(shopName, tableName, callNum, preNum, codeUrl, shopNote, takeTime);
|
||||
sendPrintRequest(machine.getAddress(), resp, null, "1");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 交班单打印
|
||||
*/
|
||||
@Override
|
||||
protected void handoverPrint(PrintMachine machine, HandoverRecordDTO record) {
|
||||
String string = buildHandoverData(record);
|
||||
@@ -214,9 +205,9 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
||||
* @param requestId 请求ID,自定义
|
||||
* @return token信息
|
||||
*/
|
||||
private static Map<String, String> getToken(String timestamp, String requestId) {
|
||||
private static String getToken(String timestamp, String requestId) {
|
||||
StringBuilder token = new StringBuilder();
|
||||
StringBuilder encode = new StringBuilder();
|
||||
// StringBuilder encode = new StringBuilder();
|
||||
SortedMap<String, Object> map = new TreeMap<>();
|
||||
map.put("appId", APP_ID);
|
||||
map.put("timestamp", timestamp);
|
||||
@@ -226,13 +217,38 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
|
||||
String key = next.getKey();
|
||||
Object value = next.getValue();
|
||||
token.append(key).append(value);
|
||||
encode.append(key).append("=").append(value).append("&");
|
||||
// encode.append(key).append("=").append(value).append("&");
|
||||
}
|
||||
Map<String, String> finalMap = new HashMap<>();
|
||||
finalMap.put("ENCODE", encode.toString());
|
||||
finalMap.put("TOKEN", SecureUtil.md5(token + APP_SECRET).toUpperCase());
|
||||
return finalMap;
|
||||
// Map<String, String> finalMap = new HashMap<>();
|
||||
// finalMap.put("ENCODE", encode.toString());
|
||||
// finalMap.put("TOKEN", SecureUtil.md5(token + APP_SECRET).toUpperCase());
|
||||
// return finalMap;
|
||||
return SecureUtil.md5(token + APP_SECRET).toUpperCase();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检查打印状态
|
||||
*
|
||||
* @param devName 设备名称,(唯一) 对应配置表中的address字段即(IP地址/打印机编号)
|
||||
* @param taskId 打印任务id,用于复查打印状态,云想印=orderId
|
||||
*/
|
||||
public String checkPrintStatus(String devName, String taskId) {
|
||||
String time = String.valueOf(System.currentTimeMillis());
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
|
||||
paramMap.put("devName", devName);
|
||||
paramMap.put("orderId", taskId);
|
||||
paramMap.put("token", getToken(time, uuid));
|
||||
paramMap.put("appId", APP_ID);
|
||||
paramMap.put("timestamp", time);
|
||||
paramMap.put("requestId", uuid);
|
||||
paramMap.put("userCode", USER_CODE);
|
||||
String s = HttpUtil.get("https://ioe.car900.com/v1/openApi/dev/findOrder.json", paramMap, 1000 * 5);
|
||||
log.info("云想印打印机:{},任务:{}状态:{}", devName, taskId, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1523,13 +1523,13 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
|
||||
|
||||
switch (orderInfoPrintDTO.getType()) {
|
||||
case 0:
|
||||
printerHandler.handler(orderInfo.getId().toString(), PrinterHandler.PrintTypeEnum.ONE_AND_ORDER, orderInfoPrintDTO.getMachineId());
|
||||
printerHandler.handler(orderInfo.getId().toString(), PrinterHandler.PrintTypeEnum.ONE_AND_ORDER);
|
||||
break;
|
||||
case 1:
|
||||
printerHandler.handler(orderInfo.getId().toString(), PrinterHandler.PrintTypeEnum.PRE_ORDER, orderInfoPrintDTO.getMachineId());
|
||||
printerHandler.handler(orderInfo.getId().toString(), PrinterHandler.PrintTypeEnum.PRE_ORDER);
|
||||
break;
|
||||
case 2:
|
||||
printerHandler.handler(orderInfo.getId().toString(), PrinterHandler.PrintTypeEnum.ORDER, orderInfoPrintDTO.getMachineId());
|
||||
printerHandler.handler(orderInfo.getId().toString(), PrinterHandler.PrintTypeEnum.ORDER);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -2,28 +2,31 @@ package com.czg.service.order.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.text.UnicodeUtil;
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.account.entity.PrintMachine;
|
||||
import com.czg.market.service.OrderInfoService;
|
||||
import com.czg.order.entity.PrintMachineLog;
|
||||
import com.czg.order.service.PrintMachineLogService;
|
||||
import com.czg.service.order.mapper.PrintMachineLogMapper;
|
||||
import com.czg.service.order.print.FeiPrinter;
|
||||
import com.czg.service.order.print.YxyPrinter;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* 店铺小票打印记录ServiceImpl
|
||||
@@ -35,135 +38,22 @@ import java.util.*;
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PrintMachineLogServiceImpl extends ServiceImpl<PrintMachineLogMapper, PrintMachineLog> implements PrintMachineLogService {
|
||||
//请求地址
|
||||
private static final String URL_STR = "https://ioe.car900.com/v1/openApi/dev/customPrint.json";
|
||||
//APPID
|
||||
private static final String APP_ID = "ZF544";
|
||||
//USERCODE
|
||||
private static final String USER_CODE = "ZF544";
|
||||
//APPSECRET
|
||||
private static final String APP_SECRET = "2022bsjZF544GAH";
|
||||
|
||||
public static final String URL = "http://api.feieyun.cn/Api/Open/";//不需要修改
|
||||
|
||||
public static final String USER = "chaozhanggui2022@163.com";//*必填*:账号名
|
||||
public static final String UKEY = "UfWkhXxSkeSSscsU";//*必填*: 飞鹅云后台注册账号后生成的UKEY 【备注:这不是填打印机的KEY】
|
||||
public static final String SN = "960238952";//*必填*:打印机编号,必须要在管理后台里添加打印机或调用API接口添加之后,才能调用API
|
||||
|
||||
@Resource
|
||||
private OrderInfoService orderInfoService;
|
||||
@Lazy
|
||||
@Resource
|
||||
private YxyPrinter yxyPrinter;
|
||||
@Lazy
|
||||
@Resource
|
||||
private FeiPrinter feiPrinter;
|
||||
|
||||
/**
|
||||
* 获取TOKEN值
|
||||
*
|
||||
* @param timestamp 时间戳,13位
|
||||
* @param requestId 请求ID,自定义
|
||||
* @return
|
||||
*/
|
||||
private static Map<String, String> getToken(String timestamp, String requestId) {
|
||||
StringBuilder token = new StringBuilder();
|
||||
StringBuilder encode = new StringBuilder();
|
||||
SortedMap<String, Object> map = new TreeMap<>();
|
||||
map.put("appId", APP_ID);
|
||||
map.put("timestamp", timestamp);
|
||||
map.put("requestId", requestId);
|
||||
map.put("userCode", USER_CODE);
|
||||
for (Map.Entry<String, Object> next : map.entrySet()) {
|
||||
String key = next.getKey();
|
||||
Object value = next.getValue();
|
||||
token.append(key).append(value);
|
||||
encode.append(key).append("=").append(value).append("&");
|
||||
}
|
||||
System.out.println("token" + token);
|
||||
Map<String, String> finalMap = new HashMap<>();
|
||||
finalMap.put("ENCODE", encode.toString());
|
||||
finalMap.put("TOKEN", SecureUtil.md5(token + APP_SECRET).toUpperCase());
|
||||
return finalMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查打印状态
|
||||
*
|
||||
* @param devName 设备名称,(唯一) 对应配置表中的address字段即(IP地址/打印机编号)
|
||||
* @param taskId 打印任务id,用于复查打印状态,云想印=orderId
|
||||
* @return
|
||||
*/
|
||||
public static String checkPrintStatus(String devName, String taskId) {
|
||||
String time = String.valueOf(System.currentTimeMillis());
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
|
||||
Map<String, String> param = getToken(time, uuid);
|
||||
String token = param.get("TOKEN");
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
|
||||
paramMap.put("devName", devName);
|
||||
paramMap.put("orderId", taskId);
|
||||
paramMap.put("token", token);
|
||||
paramMap.put("appId", APP_ID);
|
||||
paramMap.put("timestamp", time);
|
||||
paramMap.put("requestId", uuid);
|
||||
paramMap.put("userCode", USER_CODE);
|
||||
|
||||
return HttpUtil.get("https://ioe.car900.com/v1/openApi/dev/findOrder.json", paramMap, 1000 * 5);
|
||||
}
|
||||
|
||||
private static String signature(String USER, String UKEY, String STIME) {
|
||||
return DigestUtils.sha1Hex(USER + UKEY + STIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查飞鹅打印机打印任务是否已打印
|
||||
*
|
||||
* @param printOrderId 打印订单编号
|
||||
* @return null-未知错误,true-已打印,false-未打印
|
||||
*/
|
||||
public static Boolean checkFPrintStatus(String printOrderId) {
|
||||
String STIME = String.valueOf(System.currentTimeMillis() / 1000);
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
paramMap.put("user", USER);
|
||||
paramMap.put("stime", STIME);
|
||||
paramMap.put("sig", signature(USER, UKEY, STIME));
|
||||
paramMap.put("apiname", "Open_queryOrderState");
|
||||
paramMap.put("orderid", printOrderId);
|
||||
Boolean ret;
|
||||
try {
|
||||
String resp = HttpUtil.post(URL, paramMap, 1000 * 5);
|
||||
//成功 {"msg":"ok","ret":0,"data":true,"serverExecutedTime":4}
|
||||
//失败 {"msg":"ok","ret":0,"data":false,"serverExecutedTime":4}
|
||||
JSONObject json = JSONUtil.parseObj(UnicodeUtil.toString(resp));
|
||||
ret = json.getBool("data");
|
||||
} catch (Exception e) {
|
||||
ret = null;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查飞鹅打印机是否在线
|
||||
*
|
||||
* @param sn 设备编号
|
||||
* @return 在线,工作状态正常。/离线。/未知错误
|
||||
*/
|
||||
public static String checkOnline(String sn) {
|
||||
String STIME = String.valueOf(System.currentTimeMillis() / 1000);
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
paramMap.put("user", USER);
|
||||
paramMap.put("stime", STIME);
|
||||
paramMap.put("sig", signature(USER, UKEY, STIME));
|
||||
paramMap.put("apiname", "Open_queryPrinterStatus");
|
||||
paramMap.put("sn", sn);
|
||||
String msg;
|
||||
try {
|
||||
String resp = HttpUtil.post(URL, paramMap, 1000 * 5);
|
||||
//成功 开机 {"msg":"ok","ret":0,"data":"在线,工作状态正常。","serverExecutedTime":4}
|
||||
//成功 离线 {"msg":"ok","ret":0,"data":"离线。","serverExecutedTime":7}
|
||||
JSONObject json = JSONUtil.parseObj(UnicodeUtil.toString(resp));
|
||||
msg = json.getStr("data");
|
||||
} catch (Exception e) {
|
||||
msg = "未知错误";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
Map<Integer, String> yxxStatusMap = Map.of(
|
||||
0, "离线(设备上线后自动补打)",
|
||||
1, "在线",
|
||||
2, "获取失败",
|
||||
3, "未激活",
|
||||
4, "设备已禁用");
|
||||
|
||||
/**
|
||||
* 保存打印记录
|
||||
@@ -175,7 +65,7 @@ public class PrintMachineLogServiceImpl extends ServiceImpl<PrintMachineLogMappe
|
||||
*/
|
||||
@Async
|
||||
@Override
|
||||
public void save(PrintMachine config, String bizType, String printContent, Object respJson) {
|
||||
public void save(PrintMachine config, String bizType, String printContent, String respJson) {
|
||||
if (config == null) {
|
||||
return;
|
||||
}
|
||||
@@ -184,51 +74,41 @@ public class PrintMachineLogServiceImpl extends ServiceImpl<PrintMachineLogMappe
|
||||
int failFlag = 0;
|
||||
String respCode = "0";
|
||||
String respMsg = "打印中";
|
||||
|
||||
Map<Integer, String> yxxStatusMap = MapUtil.builder(0, "离线(设备上线后自动补打)").put(1, "在线").put(2, "获取失败").put(3, "未激活").put(4, "设备已禁用").build();
|
||||
JSONObject resp = JSONObject.parseObject(respJson);
|
||||
// 云想印
|
||||
if ("云想印".equals(config.getContentType())) {
|
||||
cn.hutool.json.JSONObject resp = JSONUtil.parseObj(respJson);
|
||||
int code = resp.getInt("code");
|
||||
cn.hutool.json.JSONObject data = resp.getJSONObject("data").getJSONObject("data");
|
||||
int code = resp.getIntValue("code");
|
||||
JSONObject respData = resp.getJSONObject("data");
|
||||
JSONObject data = respData.getJSONObject("data");
|
||||
//设备状态,0: 离线, 1: 在线, 2: 获取失败, 3:未激活, 4:设备已禁用
|
||||
int status = data.getInt("status");
|
||||
int status = data.getIntValue("status");
|
||||
if (code != 0) {
|
||||
failFlag = 1;
|
||||
respCode = code + "";
|
||||
respMsg = resp.getStr("msg");
|
||||
respMsg = resp.getString("msg");
|
||||
} else if (status != 1) {
|
||||
failFlag = 1;
|
||||
respCode = code + "";
|
||||
|
||||
respMsg = status + "_" + yxxStatusMap.get(status);
|
||||
}
|
||||
if (code == 0) {
|
||||
String taskId = resp.getJSONObject("data").getStr("orderId");
|
||||
entity.setTaskId(taskId);
|
||||
entity.setTaskId(respData.getString("orderId"));
|
||||
}
|
||||
// 飞鹅云打印机暂时没有适配,先return不做打印记录
|
||||
} else if ("飞鹅".equals(config.getContentType())) {
|
||||
cn.hutool.json.JSONObject resp = JSONUtil.parseObj(respJson);
|
||||
int ret = resp.getInt("ret");
|
||||
int ret = resp.getIntValue("ret");
|
||||
if (ret != 0) {
|
||||
failFlag = 1;
|
||||
respCode = ret + "";
|
||||
respMsg = resp.getStr("msg");
|
||||
respMsg = resp.getString("msg");
|
||||
} else {
|
||||
String printOrderId = resp.getStr("data");
|
||||
entity.setTaskId(printOrderId);
|
||||
entity.setTaskId(resp.getString("data"));
|
||||
}
|
||||
} else {
|
||||
// 其他打印机暂时没有适配,先return不做打印记录
|
||||
return;
|
||||
}
|
||||
entity.setBizType(bizType);
|
||||
// entity.setCreateUserId(config.getCurrentUserId());
|
||||
// entity.setCreateUserName(config.getCurrentUserName());
|
||||
// if (StrUtil.isNotBlank(config.getCurrentUserNickName())) {
|
||||
// entity.setCreateUserName(StrUtil.concat(true, config.getCurrentUserNickName(), " | ", config.getCurrentUserName()));
|
||||
// }
|
||||
entity.setPrintContent(printContent);
|
||||
entity.setCreateTime(DateUtil.date().toLocalDateTime());
|
||||
if (failFlag == 0) {
|
||||
@@ -238,64 +118,251 @@ public class PrintMachineLogServiceImpl extends ServiceImpl<PrintMachineLogMappe
|
||||
entity.setRespCode(respCode);
|
||||
entity.setRespMsg(respMsg);
|
||||
super.save(entity);
|
||||
ThreadUtil.execAsync(() -> checkPrintStatus(config, entity));
|
||||
}
|
||||
|
||||
// 云想印
|
||||
/**
|
||||
* 类级别成员变量:基于虚拟线程的固定大小(5)定时线程池
|
||||
* // Java 21+ 虚拟线程工厂,支持命名
|
||||
*/
|
||||
private final ScheduledExecutorService virtualThreadScheduler = Executors.newScheduledThreadPool(
|
||||
5,
|
||||
Thread.ofVirtual().name("print-query-vt-", 0).factory()
|
||||
);
|
||||
|
||||
/**
|
||||
* 打印机状态查询(解决 retryFuture 爆红问题 + 虚拟线程 + 轮询重试)
|
||||
*
|
||||
* @param config 打印机配置
|
||||
* @param entity 打印日志实体
|
||||
*/
|
||||
public void checkPrintStatus(PrintMachine config, PrintMachineLog entity) {
|
||||
// 最大重试次数
|
||||
int maxRetryTimes = 5;
|
||||
AtomicInteger executedTimes = new AtomicInteger(0);
|
||||
|
||||
// 原子引用包装ScheduledFuture,用于后续取消轮询
|
||||
AtomicReference<ScheduledFuture<?>> retryFutureRef = new AtomicReference<>();
|
||||
|
||||
// 核心查询任务(修正后,逻辑内聚)
|
||||
Runnable printQueryTask = () -> {
|
||||
int currentTimes = executedTimes.incrementAndGet();
|
||||
boolean isPrintSuccess = false;
|
||||
boolean isLastTask = false;
|
||||
|
||||
try {
|
||||
// 1. 云想印打印机状态查询
|
||||
if ("云想印".equals(config.getContentType())) {
|
||||
// 延迟3ms,复查打印状态 (用户可以根据设备信息查询到当前设备的在线情况(注:该接口只能提供参考,设备的离线状态是在设备离线3分钟后才会生效))
|
||||
ThreadUtil.safeSleep(1000 * 5);
|
||||
String jsonStr = checkPrintStatus(config.getAddress(), entity.getTaskId());
|
||||
cn.hutool.json.JSONObject resp = JSONUtil.parseObj(jsonStr);
|
||||
int code = resp.getInt("code");
|
||||
String jsonStr = yxyPrinter.checkPrintStatus(config.getAddress(), entity.getTaskId());
|
||||
log.info("云想印打印状态查询结果(第{}次,虚拟线程:{}):{}",
|
||||
currentTimes, Thread.currentThread().getName(), jsonStr);
|
||||
JSONObject resp = JSONObject.parseObject(jsonStr);
|
||||
int code = resp.getIntValue("code");
|
||||
if (code == 0) {
|
||||
cn.hutool.json.JSONObject data = resp.getJSONObject("data");
|
||||
boolean status = data.containsKey("status");
|
||||
if (!status) {
|
||||
return;
|
||||
}
|
||||
boolean success = data.getBool("status", false);
|
||||
if (entity.getFailFlag() == 0 && success) {
|
||||
entity.setFailFlag(0);
|
||||
entity.setRespMsg("打印成功");
|
||||
entity.setPrintTime(entity.getCreateTime());
|
||||
} else if (entity.getFailFlag() == 1 && success) {
|
||||
entity.setFailFlag(0);
|
||||
entity.setPrintTime(DateUtil.date().toLocalDateTime());
|
||||
entity.setRespMsg("打印成功");
|
||||
// 如果设备在线 and 休眠5秒后查询结果是未打印,即视为设备已离线,云端3分钟后才会同步到离线信息
|
||||
} else if (entity.getFailFlag() == 0 && !success) {
|
||||
entity.setFailFlag(1);
|
||||
entity.setPrintTime(null);
|
||||
entity.setRespMsg("0_离线(设备上线后自动补打)");
|
||||
} else {
|
||||
entity.setFailFlag(1);
|
||||
entity.setPrintTime(null);
|
||||
entity.setRespMsg(StrUtil.concat(true, "打印失败,", "_", entity.getRespMsg()));
|
||||
JSONObject data = resp.getJSONObject("data");
|
||||
if (data.containsKey("status")) {
|
||||
isPrintSuccess = data.getBooleanValue("status", false);
|
||||
updatePrintLogEntity(entity, isPrintSuccess);
|
||||
}
|
||||
}
|
||||
// 飞鹅云打印机
|
||||
} else if ("飞鹅".equals(config.getContentType())) {
|
||||
ThreadUtil.safeSleep(1000 * 5);
|
||||
Boolean success = checkFPrintStatus(entity.getTaskId());
|
||||
}
|
||||
// 2. 飞鹅云打印机状态查询
|
||||
else if ("飞鹅".equals(config.getContentType())) {
|
||||
Boolean success = feiPrinter.checkFPrintStatus(entity.getTaskId());
|
||||
if (success == null) {
|
||||
entity.setFailFlag(1);
|
||||
entity.setRespMsg("打印失败,未知错误");
|
||||
entity.setPrintTime(null);
|
||||
} else if (success) {
|
||||
entity.setFailFlag(0);
|
||||
entity.setPrintTime(DateUtil.date().toLocalDateTime());
|
||||
entity.setRespMsg("打印成功");
|
||||
isPrintSuccess = true;
|
||||
updatePrintLogEntity(entity, true);
|
||||
} else {
|
||||
String msg = checkOnline(entity.getAddress());
|
||||
String msg = feiPrinter.checkOnline(entity.getAddress());
|
||||
if (msg.indexOf("在线,工作状态正常") > 0) {
|
||||
entity.setFailFlag(0);
|
||||
entity.setPrintTime(DateUtil.date().toLocalDateTime());
|
||||
entity.setRespMsg("打印成功");
|
||||
isPrintSuccess = true;
|
||||
updatePrintLogEntity(entity, true);
|
||||
} else {
|
||||
isPrintSuccess = false;
|
||||
entity.setFailFlag(1);
|
||||
entity.setPrintTime(null);
|
||||
entity.setRespMsg(StrUtil.concat(true, "打印失败,", "_", msg));
|
||||
}
|
||||
}
|
||||
}else {
|
||||
log.info("打印类型为其他类型,终止打印状态查询轮询任务");
|
||||
ScheduledFuture<?> future = retryFutureRef.get();
|
||||
if (future != null && !future.isCancelled()) {
|
||||
boolean cancelSuccess = future.cancel(false); // 取消后续轮询(不中断当前任务)
|
||||
log.info("其他打印类型,取消轮询任务:{}", cancelSuccess ? "成功" : "失败");
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 打印成功:取消后续轮询任务
|
||||
if (isPrintSuccess) {
|
||||
isLastTask = true;
|
||||
ScheduledFuture<?> future = retryFutureRef.get();
|
||||
if (future != null && !future.isCancelled()) {
|
||||
future.cancel(false); // 不中断当前任务,仅取消后续任务
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. 达到最大重试次数:取消后续轮询任务
|
||||
if (currentTimes >= maxRetryTimes) {
|
||||
isLastTask = true;
|
||||
ScheduledFuture<?> future = retryFutureRef.get();
|
||||
if (future != null && !future.isCancelled()) {
|
||||
future.cancel(false);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("第{}次打印机状态查询异常(虚拟线程:{})",
|
||||
currentTimes, Thread.currentThread().getName(), e);
|
||||
// 异常时达到最大重试次数,同样取消任务
|
||||
if (currentTimes >= maxRetryTimes) {
|
||||
ScheduledFuture<?> future = retryFutureRef.get();
|
||||
if (future != null && !future.isCancelled()) {
|
||||
boolean cancelSuccess = future.cancel(false);
|
||||
log.info("查询异常且达到最大重试次数,取消轮询任务:{}", cancelSuccess ? "成功" : "失败");
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
//仅当是最后一次任务时,才执行更新操作
|
||||
if (isLastTask) {
|
||||
super.updateById(entity);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 修正:统一使用scheduleAtFixedRate,避免任务重复执行
|
||||
// 首次延迟10秒执行,后续每隔30秒执行一次(符合原逻辑的首次查询延迟,后续轮询间隔)
|
||||
ScheduledFuture<?> retryFuture = virtualThreadScheduler.scheduleAtFixedRate(
|
||||
printQueryTask,
|
||||
10,
|
||||
30,
|
||||
TimeUnit.SECONDS
|
||||
);
|
||||
|
||||
// 修正:先赋值AtomicReference,再让任务可能执行,避免线程安全隐患
|
||||
retryFutureRef.set(retryFuture);
|
||||
// 修正:关闭钩子仅注册一次(通过静态代码块或类初始化时注册,避免重复注册)
|
||||
registerShutdownHookOnce();
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一更新打印日志实体
|
||||
*
|
||||
* @param entity 打印日志实体
|
||||
* @param isPrintSuccess 是否打印成功
|
||||
*/
|
||||
private void updatePrintLogEntity(PrintMachineLog entity, boolean isPrintSuccess) {
|
||||
if (isPrintSuccess) {
|
||||
entity.setFailFlag(0);
|
||||
entity.setRespMsg("打印成功");
|
||||
entity.setPrintTime(entity.getFailFlag() == 0 ? entity.getCreateTime() : DateUtil.date().toLocalDateTime());
|
||||
} else {
|
||||
entity.setFailFlag(1);
|
||||
entity.setPrintTime(null);
|
||||
if (entity.getFailFlag() == 0) {
|
||||
entity.setRespMsg("0_离线(设备上线后自动补打)");
|
||||
} else {
|
||||
entity.setRespMsg(StrUtil.concat(true, "打印失败,", "_", entity.getRespMsg()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// public void checkPrintStatus(PrintMachine config, PrintMachineLog entity) {
|
||||
// // 云想印
|
||||
// if ("云想印".equals(config.getContentType())) {
|
||||
// String jsonStr = yxyPrinter.checkPrintStatus(config.getAddress(), entity.getTaskId());
|
||||
// log.info("云想印打印状态查询结果:{}", jsonStr);
|
||||
// JSONObject resp = JSONObject.parseObject(jsonStr);
|
||||
// int code = resp.getIntValue("code");
|
||||
// if (code == 0) {
|
||||
// JSONObject data = resp.getJSONObject("data");
|
||||
// boolean status = data.containsKey("status");
|
||||
// if (!status) {
|
||||
// return;
|
||||
// }
|
||||
// boolean success = data.getBooleanValue("status", false);
|
||||
// if (entity.getFailFlag() == 0 && success) {
|
||||
// entity.setFailFlag(0);
|
||||
// entity.setRespMsg("打印成功");
|
||||
// entity.setPrintTime(entity.getCreateTime());
|
||||
// } else if (entity.getFailFlag() == 1 && success) {
|
||||
// entity.setFailFlag(0);
|
||||
// entity.setPrintTime(DateUtil.date().toLocalDateTime());
|
||||
// entity.setRespMsg("打印成功");
|
||||
// // 如果设备在线 and 休眠5秒后查询结果是未打印,即视为设备已离线,云端3分钟后才会同步到离线信息
|
||||
// } else if (entity.getFailFlag() == 0 && !success) {
|
||||
// entity.setFailFlag(1);
|
||||
// entity.setPrintTime(null);
|
||||
// entity.setRespMsg("0_离线(设备上线后自动补打)");
|
||||
// } else {
|
||||
// entity.setFailFlag(1);
|
||||
// entity.setPrintTime(null);
|
||||
// entity.setRespMsg(StrUtil.concat(true, "打印失败,", "_", entity.getRespMsg()));
|
||||
// }
|
||||
// }
|
||||
// // 飞鹅云打印机
|
||||
// } else if ("飞鹅".equals(config.getContentType())) {
|
||||
// Boolean success = feiPrinter.checkFPrintStatus(entity.getTaskId());
|
||||
// if (success == null) {
|
||||
// entity.setFailFlag(1);
|
||||
// entity.setRespMsg("打印失败,未知错误");
|
||||
// } else if (success) {
|
||||
// entity.setFailFlag(0);
|
||||
// entity.setPrintTime(DateUtil.date().toLocalDateTime());
|
||||
// entity.setRespMsg("打印成功");
|
||||
// } else {
|
||||
// String msg = feiPrinter.checkOnline(entity.getAddress());
|
||||
// if (msg.indexOf("在线,工作状态正常") > 0) {
|
||||
// entity.setFailFlag(0);
|
||||
// entity.setPrintTime(DateUtil.date().toLocalDateTime());
|
||||
// entity.setRespMsg("打印成功");
|
||||
// } else {
|
||||
// entity.setFailFlag(1);
|
||||
// entity.setPrintTime(null);
|
||||
// entity.setRespMsg(StrUtil.concat(true, "打印失败,", "_", msg));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// super.updateById(entity);
|
||||
// }
|
||||
|
||||
// 静态标识,确保关闭钩子仅注册一次
|
||||
private static volatile boolean shutdownHookRegistered = false;
|
||||
// 锁对象,保证线程安全
|
||||
private static final Object HOOK_LOCK = new Object();
|
||||
|
||||
/**
|
||||
* 统一注册JVM关闭钩子(仅执行一次)
|
||||
*/
|
||||
private void registerShutdownHookOnce() {
|
||||
if (!shutdownHookRegistered) {
|
||||
synchronized (HOOK_LOCK) {
|
||||
// 双重校验锁,避免多线程下重复注册
|
||||
if (!shutdownHookRegistered) {
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
if (virtualThreadScheduler != null && !virtualThreadScheduler.isShutdown()) {
|
||||
virtualThreadScheduler.shutdown();
|
||||
try {
|
||||
if (!virtualThreadScheduler.awaitTermination(10, TimeUnit.SECONDS)) {
|
||||
log.warn("虚拟线程调度器10秒内未关闭,强制关闭...");
|
||||
virtualThreadScheduler.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
log.error("等待虚拟线程调度器终止时被中断,强制关闭", e);
|
||||
virtualThreadScheduler.shutdownNow();
|
||||
Thread.currentThread().interrupt(); // 保留中断状态
|
||||
}
|
||||
}
|
||||
}, "PrinterScheduler-ShutdownHook"));
|
||||
shutdownHookRegistered = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user