打印问题

This commit is contained in:
2025-12-30 11:49:54 +08:00
parent 7384b67c50
commit befd2942a2
8 changed files with 107 additions and 26 deletions

View File

@@ -25,7 +25,30 @@ spring:
port: 5672
username: chaozg
password: chaozg123
# 关键优化解决MissedHeartbeatException 心跳超时问题
connection-timeout: 10000 # 连接超时时间10秒避免连接建立过慢
requested-heartbeat: 30 # 心跳间隔调整为30秒原60秒过长降低超时概率过短易误触发
# 高级配置:连接池 & 自动重连(核心优化,避免连接断开后无法恢复)
cache:
connection:
mode: channel # 连接池模式默认channel推荐
size: 10 # 最大连接数,根据业务调整
channel:
size: 50 # 每个连接的最大通道数
# 自动重连配置Spring AMQP 自带,关键兜底)
publisher-returns: true
template:
retry:
enabled: true # 开启消息发送重试
max-attempts: 3 # 最大重试次数
initial-interval: 2000 # 首次重试间隔2秒
multiplier: 1.5 # 重试间隔倍增因子
listener:
simple:
retry:
enabled: true # 开启消费者重试
max-attempts: 3 # 消费者最大重试次数
acknowledge-mode: auto # 确认模式可根据业务改为manual
dubbo:
application:
name: order-server

View File

@@ -2,6 +2,7 @@ package com.czg.order.entity;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.czg.order.dto.LimitRateDTO;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
@@ -346,15 +347,38 @@ public class OrderInfo implements Serializable {
// .add(this.getRoundAmount() != null ? this.getRoundAmount() : BigDecimal.ZERO);
}
private JSONArray getPrintStatusAsArray() {
if (StrUtil.isBlank(printStatus)) {
return new JSONArray();
}
try {
return JSONArray.parseArray(printStatus.trim());
} catch (Exception e) {
return new JSONArray();
}
}
// public JSONArray getPrintStatus() {
// if (StrUtil.isBlank(printStatus)) {
// return new JSONArray();
// }
// try {
// return JSONArray.parseArray(printStatus.trim());
// } catch (Exception e) {
// return new JSONArray();
// }
// }
public void upPrintStatus(JSONObject printStatus, boolean isPrintSuccess) {
String currentDeviceId = printStatus.getString("id");
JSONArray oldPrintStatusArray = getPrintStatusAsArray();
// 3. 初始化新的打印状态JSON数组用于存储处理后的结果
JSONArray newPrintStatusArray = new JSONArray();
// 场景1打印成功 - 移除原有数组中与当前设备ID一致的记录保留其余记录
if (oldPrintStatusArray != null && !oldPrintStatusArray.isEmpty()) {
for (int i = 0; i < oldPrintStatusArray.size(); i++) {
JSONObject deviceObj = oldPrintStatusArray.getJSONObject(i);
String deviceId = deviceObj.getString("id");
// 仅保留非当前设备ID的记录
if (currentDeviceId != null && !currentDeviceId.equals(deviceId)) {
newPrintStatusArray.add(deviceObj);
}
}
}
if (!isPrintSuccess) {
newPrintStatusArray.add(printStatus);
}
if(newPrintStatusArray.isEmpty()){
this.setPrintStatus(newPrintStatusArray.toJSONString());
}
}
}

View File

@@ -11,6 +11,8 @@ import com.czg.order.entity.PrintMachineLog;
* @since 2025-03-11
*/
public interface PrintMachineLogService extends IService<PrintMachineLog> {
void save(Long orderId, PrintMachine config, String bizType, String printContent, String respJson);
void save(PrintMachine config, String bizType, String printContent, String respJson);
}

View File

@@ -70,7 +70,7 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
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());
String o = sendPrintRequest(machine.getAddress(), content, null, "1");
printMachineLogService.save(machine, "新订单", content, o);
printMachineLogService.save(orderInfo.getId(), machine, "新订单", content, o);
}
@@ -80,7 +80,7 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
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());
String o = sendPrintRequest(machine.getAddress(), content, null, "1");
printMachineLogService.save(machine, "退款单", content, o);
printMachineLogService.save(orderInfo.getId(), machine, "退款单", content, o);
}
@@ -102,7 +102,7 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
.setDiscountAmount(orderInfo.getOriginAmount().subtract(orderInfo.getPayAmount()).toPlainString());
String string = buildOrderPrintData(printInfoDTO, detailList);
String o = sendPrintRequest(machine.getAddress(), string, null, printerNum);
printMachineLogService.save(machine, "结算单", string, o);
printMachineLogService.save(orderInfo.getId(), machine, "结算单", string, o);
}
@@ -139,7 +139,7 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
String string = buildOrderPrintData(printInfoDTO, detailList);
String resp = sendPrintRequest(machine.getAddress(), string, null, printerNum);
printMachineLogService.save(machine, "结算单", string, resp);
printMachineLogService.save(orderInfo.getId(), machine, "结算单", string, resp);
}
@Override

View File

@@ -342,6 +342,7 @@ public abstract class PrinterHandler {
case PrintTypeEnum.ORDER:
log.info("准备开始打印订单");
if (data instanceof OrderInfo orderInfo) {
redisService.set("order:print:" + orderInfo.getId(),"", 180);
List<OrderDetail> orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()));
onlyFrontDesk(machine, false, orderInfo, orderDetailList);
} else {
@@ -351,6 +352,7 @@ public abstract class PrinterHandler {
case PrintTypeEnum.PRE_ORDER:
log.info("准备开始打印预结算订单");
if (data instanceof OrderInfo orderInfo) {
redisService.set("order:print:" + orderInfo.getId(),"", 180);
List<OrderDetail> orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()));
onlyFrontDesk(machine, true, orderInfo, orderDetailList);
} else {
@@ -360,6 +362,7 @@ public abstract class PrinterHandler {
case PrintTypeEnum.ONE:
log.info("准备开始打印菜品单");
if (data instanceof OrderInfo orderInfo) {
redisService.set("order:print:" + orderInfo.getId(),"", 180);
List<OrderDetail> orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()));
onlyKitchen(machine, orderInfo, orderDetailList);
} else {
@@ -377,6 +380,7 @@ public abstract class PrinterHandler {
case PrintTypeEnum.ONE_AND_ORDER:
log.info("准备开始打印菜品以及结算单");
if (data instanceof OrderInfo orderInfo) {
redisService.set("order:print:" + orderInfo.getId(),"", 180);
List<OrderDetail> orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()));
switch (machine.getPrintMethod()) {
case "all":
@@ -462,7 +466,7 @@ 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())
.setPrintNum(orderDetail.getNum()).setPrintReturnNum(orderDetail.getReturnNum())), 3600 * 24);
.setPrintNum(orderDetail.getNum()).setPrintReturnNum(orderDetail.getReturnNum())), 3600 * 24);
});

View File

@@ -107,7 +107,7 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
orderDetail.getNum(), orderDetail.getRemark(), orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
String voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}";
String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1");
printMachineLogService.save(machine, "新订单", buildDishPrintData, resp);
printMachineLogService.save(orderInfo.getId(), machine, "新订单", buildDishPrintData, resp);
}
@@ -117,7 +117,7 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
orderDetail.getReturnNum(), orderDetail.getRemark(), orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}";
String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1");
printMachineLogService.save(machine, "退款单", buildDishPrintData, resp);
printMachineLogService.save(orderInfo.getId(), machine, "退款单", buildDishPrintData, resp);
}
@@ -138,7 +138,7 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
printerNum = machine.getPrintQty().split("\\^")[1];
}
String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, printerNum);
printMachineLogService.save(machine, "退款单", data, resp);
printMachineLogService.save(orderInfo.getId(), machine, "退款单", data, resp);
}
@@ -174,7 +174,7 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
printerNum = machine.getPrintQty().split("\\^")[1];
}
String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, printerNum);
printMachineLogService.save(machine, "结算单", data, resp);
printMachineLogService.save(orderInfo.getId(), machine, "结算单", data, resp);
}

View File

@@ -1516,6 +1516,9 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
@Override
public Boolean printOrder(Long shopId, OrderInfoPrintDTO orderInfoPrintDTO) {
if (redisService.hasKey("order:print:" + orderInfoPrintDTO.getId())) {
throw new CzgException("网络打印机正在尝试打印中。如需重打,请稍后再试!");
}
OrderInfo orderInfo = orderInfoService.getOne(new QueryWrapper().eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getId, orderInfoPrintDTO.getId()));
if (orderInfo == null) {
throw new CzgException("订单信息不存在");

View File

@@ -4,11 +4,14 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.czg.account.entity.PrintMachine;
import com.czg.market.service.OrderInfoService;
import com.czg.order.entity.OrderInfo;
import com.czg.order.entity.PrintMachineLog;
import com.czg.order.service.PrintMachineLogService;
import com.czg.service.RedisService;
import com.czg.service.order.mapper.PrintMachineLogMapper;
import com.czg.service.order.print.FeiPrinter;
import com.czg.service.order.print.YxyPrinter;
@@ -20,6 +23,7 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -47,6 +51,8 @@ public class PrintMachineLogServiceImpl extends ServiceImpl<PrintMachineLogMappe
@Lazy
@Resource
private FeiPrinter feiPrinter;
@Resource
private RedisService redisService;
Map<Integer, String> yxxStatusMap = Map.of(
0, "离线(设备上线后自动补打)",
@@ -55,9 +61,19 @@ public class PrintMachineLogServiceImpl extends ServiceImpl<PrintMachineLogMappe
3, "未激活",
4, "设备已禁用");
@Async
@Override
public void save(PrintMachine config, String bizType, String printContent, String respJson) {
if (config == null) {
return;
}
save(null, config, bizType, printContent, respJson);
}
/**
* 保存打印记录
*
* @param orderId 订单Id
* @param config 打印机配置
* @param bizType 业务类型
* @param printContent 打印内容
@@ -65,7 +81,7 @@ public class PrintMachineLogServiceImpl extends ServiceImpl<PrintMachineLogMappe
*/
@Async
@Override
public void save(PrintMachine config, String bizType, String printContent, String respJson) {
public void save(Long orderId, PrintMachine config, String bizType, String printContent, String respJson) {
if (config == null) {
return;
}
@@ -118,7 +134,7 @@ public class PrintMachineLogServiceImpl extends ServiceImpl<PrintMachineLogMappe
entity.setRespCode(respCode);
entity.setRespMsg(respMsg);
super.save(entity);
ThreadUtil.execAsync(() -> checkPrintStatus(config, entity));
ThreadUtil.execAsync(() -> checkPrintStatus(orderId, config, entity));
}
/**
@@ -133,10 +149,11 @@ public class PrintMachineLogServiceImpl extends ServiceImpl<PrintMachineLogMappe
/**
* 打印机状态查询(解决 retryFuture 爆红问题 + 虚拟线程 + 轮询重试)
*
* @param config 打印机配置
* @param entity 打印日志实体
* @param orderId 订单Id
* @param config 打印机配置
* @param entity 打印日志实体
*/
public void checkPrintStatus(PrintMachine config, PrintMachineLog entity) {
public void checkPrintStatus(Long orderId, PrintMachine config, PrintMachineLog entity) {
// 最大重试次数
int maxRetryTimes = 5;
AtomicInteger executedTimes = new AtomicInteger(0);
@@ -188,7 +205,7 @@ public class PrintMachineLogServiceImpl extends ServiceImpl<PrintMachineLogMappe
entity.setRespMsg(StrUtil.concat(true, "打印失败,", "_", msg));
}
}
}else {
} else {
log.info("打印类型为其他类型,终止打印状态查询轮询任务");
ScheduledFuture<?> future = retryFutureRef.get();
if (future != null && !future.isCancelled()) {
@@ -230,7 +247,15 @@ public class PrintMachineLogServiceImpl extends ServiceImpl<PrintMachineLogMappe
} finally {
//仅当是最后一次任务时,才执行更新操作
if (isLastTask) {
redisService.del("order:print:" + orderId);
super.updateById(entity);
OrderInfo orderInfo = orderInfoService.getOne(query().select(OrderInfo::getPrintStatus).eq(OrderInfo::getId, orderId));
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", config.getId());
jsonObject.put("name", config.getName());
jsonObject.put("time", LocalDateTime.now());
orderInfo.upPrintStatus(jsonObject, isPrintSuccess);
orderInfoService.update(orderInfo, query().eq(OrderInfo::getId, orderId));
}
}
};