This commit is contained in:
van
2026-04-21 23:37:18 +08:00
parent a10d561fcb
commit de335831d4
7 changed files with 102 additions and 36 deletions

View File

@@ -12,8 +12,9 @@ public class GoofishAsyncConfig {
@Bean("goofishTaskExecutor") @Bean("goofishTaskExecutor")
public Executor goofishTaskExecutor() { public Executor goofishTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2); // 仅用于未配置 RocketMQ 时 HTTP 回调路径的 @Async过小易在拉单/回调并发时排队拖慢企微通知
executor.setMaxPoolSize(8); executor.setCorePoolSize(4);
executor.setMaxPoolSize(16);
executor.setQueueCapacity(500); executor.setQueueCapacity(500);
executor.setThreadNamePrefix("goofish-"); executor.setThreadNamePrefix("goofish-");
executor.initialize(); executor.initialize();

View File

@@ -3,7 +3,7 @@ package com.ruoyi.jarvis.mq;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.jarvis.dto.GoofishNotifyMessage; import com.ruoyi.jarvis.dto.GoofishNotifyMessage;
import com.ruoyi.jarvis.service.goofish.GoofishNotifyAsyncFacade; import com.ruoyi.jarvis.service.goofish.GoofishOrderPipeline;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener; import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -12,7 +12,10 @@ import org.springframework.stereotype.Component;
import javax.annotation.Resource; import javax.annotation.Resource;
/** /**
* 闲管家订单推送异步消费(需配置 rocketmq.name-server * 闲管家订单推送消费(需配置 rocketmq.name-server
* <p>
* 在此线程内同步执行 {@link GoofishOrderPipeline#runFullPipeline},避免再投递 {@code @Async} 线程池造成
* 「MQ 堆积 + goofishTaskExecutor 排队」的双重延迟;回调 HTTP 已在 {@link com.ruoyi.jarvis.service.impl.ErpGoofishOrderServiceImpl#publishOrProcessNotify} 中快速返回。
*/ */
@Component @Component
@ConditionalOnProperty(name = "rocketmq.name-server") @ConditionalOnProperty(name = "rocketmq.name-server")
@@ -24,7 +27,7 @@ import javax.annotation.Resource;
public class GoofishOrderNotifyConsumer implements RocketMQListener<String> { public class GoofishOrderNotifyConsumer implements RocketMQListener<String> {
@Resource @Resource
private GoofishNotifyAsyncFacade goofishNotifyAsyncFacade; private GoofishOrderPipeline goofishOrderPipeline;
@Override @Override
public void onMessage(String message) { public void onMessage(String message) {
@@ -36,6 +39,6 @@ public class GoofishOrderNotifyConsumer implements RocketMQListener<String> {
if (body == null) { if (body == null) {
body = new JSONObject(); body = new JSONObject();
} }
goofishNotifyAsyncFacade.afterNotify(m.getAppid(), body); goofishOrderPipeline.runFullPipeline(m.getAppid(), body);
} }
} }

View File

@@ -84,10 +84,10 @@ public class GoofishOrderChangeLogger {
List<String> orderParts = new ArrayList<>(); List<String> orderParts = new ArrayList<>();
if (!Objects.equals(b.orderStatus, a.orderStatus)) { if (!Objects.equals(b.orderStatus, a.orderStatus)) {
orderParts.add("order_status " + str(b.orderStatus) + "" + str(a.orderStatus)); orderParts.add("订单状态 " + str(b.orderStatus) + "" + str(a.orderStatus));
} }
if (!Objects.equals(b.refundStatus, a.refundStatus)) { if (!Objects.equals(b.refundStatus, a.refundStatus)) {
orderParts.add("refund_status " + str(b.refundStatus) + "" + str(a.refundStatus)); orderParts.add("退款状态 " + str(b.refundStatus) + "" + str(a.refundStatus));
} }
if (!orderParts.isEmpty()) { if (!orderParts.isEmpty()) {
append(afterRow.getId(), afterRow.getAppKey(), afterRow.getOrderNo(), TYPE_ORDER, source, append(afterRow.getId(), afterRow.getAppKey(), afterRow.getOrderNo(), TYPE_ORDER, source,
@@ -99,10 +99,10 @@ public class GoofishOrderChangeLogger {
logParts.add("平台运单 " + str(b.detailWaybillNo) + "" + str(a.detailWaybillNo)); logParts.add("平台运单 " + str(b.detailWaybillNo) + "" + str(a.detailWaybillNo));
} }
if (!eqStr(b.detailExpressCode, a.detailExpressCode)) { if (!eqStr(b.detailExpressCode, a.detailExpressCode)) {
logParts.add("express_code " + str(b.detailExpressCode) + "" + str(a.detailExpressCode)); logParts.add("快递编码 " + str(b.detailExpressCode) + "" + str(a.detailExpressCode));
} }
if (!eqStr(b.detailExpressName, a.detailExpressName)) { if (!eqStr(b.detailExpressName, a.detailExpressName)) {
logParts.add("express_name " + str(b.detailExpressName) + "" + str(a.detailExpressName)); logParts.add("快递名称 " + str(b.detailExpressName) + "" + str(a.detailExpressName));
} }
if (!eqStr(b.localWaybillNo, a.localWaybillNo)) { if (!eqStr(b.localWaybillNo, a.localWaybillNo)) {
logParts.add("本地运单 " + str(b.localWaybillNo) + "" + str(a.localWaybillNo)); logParts.add("本地运单 " + str(b.localWaybillNo) + "" + str(a.localWaybillNo));

View File

@@ -143,15 +143,15 @@ public class GoofishOrderPipeline {
if (existingBeforeUpdate == null) { if (existingBeforeUpdate == null) {
goofishOrderChangeLogger.append(loaded.getId(), loaded.getAppKey(), loaded.getOrderNo(), goofishOrderChangeLogger.append(loaded.getId(), loaded.getAppKey(), loaded.getOrderNo(),
GoofishOrderChangeLogger.TYPE_ORDER, upsertSource, GoofishOrderChangeLogger.TYPE_ORDER, upsertSource,
"新订单入库 order_status=" + loaded.getOrderStatus() + " refund_status=" + loaded.getRefundStatus()); "新订单入库,订单状态 " + loaded.getOrderStatus() + ",退款状态 " + loaded.getRefundStatus());
return; return;
} }
if (!Objects.equals(existingBeforeUpdate.getOrderStatus(), upsertPayload.getOrderStatus()) if (!Objects.equals(existingBeforeUpdate.getOrderStatus(), upsertPayload.getOrderStatus())
|| !Objects.equals(existingBeforeUpdate.getRefundStatus(), upsertPayload.getRefundStatus())) { || !Objects.equals(existingBeforeUpdate.getRefundStatus(), upsertPayload.getRefundStatus())) {
goofishOrderChangeLogger.append(loaded.getId(), loaded.getAppKey(), loaded.getOrderNo(), goofishOrderChangeLogger.append(loaded.getId(), loaded.getAppKey(), loaded.getOrderNo(),
GoofishOrderChangeLogger.TYPE_ORDER, upsertSource, GoofishOrderChangeLogger.TYPE_ORDER, upsertSource,
"order_status " + existingBeforeUpdate.getOrderStatus() + "" + upsertPayload.getOrderStatus() "订单状态 " + existingBeforeUpdate.getOrderStatus() + "" + upsertPayload.getOrderStatus()
+ "refund_status " + existingBeforeUpdate.getRefundStatus() + "" + upsertPayload.getRefundStatus()); + "退款状态 " + existingBeforeUpdate.getRefundStatus() + "" + upsertPayload.getRefundStatus());
} }
} }
@@ -424,7 +424,7 @@ public class GoofishOrderPipeline {
if (goofishOrderChangeLogger != null) { if (goofishOrderChangeLogger != null) {
goofishOrderChangeLogger.append(row.getId(), row.getAppKey(), row.getOrderNo(), goofishOrderChangeLogger.append(row.getId(), row.getAppKey(), row.getOrderNo(),
GoofishOrderChangeLogger.TYPE_LOGISTICS, "REDIS_WAYBILL", GoofishOrderChangeLogger.TYPE_LOGISTICS, "REDIS_WAYBILL",
"本地运单 " + (prev == null || prev.isEmpty() ? "null" : prev) + "" + wb.trim()); "本地运单 " + (prev == null || prev.isEmpty() ? "" : prev) + "" + wb.trim());
} }
} }
@@ -489,7 +489,7 @@ public class GoofishOrderPipeline {
if (goofishOrderChangeLogger != null) { if (goofishOrderChangeLogger != null) {
goofishOrderChangeLogger.append(row.getId(), row.getAppKey(), row.getOrderNo(), goofishOrderChangeLogger.append(row.getId(), row.getAppKey(), row.getOrderNo(),
GoofishOrderChangeLogger.TYPE_SHIP, "AUTO_SHIP", GoofishOrderChangeLogger.TYPE_SHIP, "AUTO_SHIP",
"发货失败(缺地址) " + (row.getShipError() != null ? row.getShipError() : "")); "发货失败(缺地址)" + (row.getShipError() != null ? row.getShipError() : ""));
} }
return; return;
} }
@@ -530,7 +530,7 @@ public class GoofishOrderPipeline {
if (goofishOrderChangeLogger != null) { if (goofishOrderChangeLogger != null) {
goofishOrderChangeLogger.append(row.getId(), row.getAppKey(), row.getOrderNo(), goofishOrderChangeLogger.append(row.getId(), row.getAppKey(), row.getOrderNo(),
GoofishOrderChangeLogger.TYPE_SHIP, "AUTO_SHIP", GoofishOrderChangeLogger.TYPE_SHIP, "AUTO_SHIP",
"发货成功 waybill=" + waybill.trim() + " expressCode=" + expressCode); "发货成功,运单 " + waybill.trim() + ",快递编码 " + expressCode);
} }
} else { } else {
String msg = r != null ? r.getString("msg") : "unknown"; String msg = r != null ? r.getString("msg") : "unknown";
@@ -538,7 +538,7 @@ public class GoofishOrderPipeline {
if (goofishOrderChangeLogger != null) { if (goofishOrderChangeLogger != null) {
goofishOrderChangeLogger.append(row.getId(), row.getAppKey(), row.getOrderNo(), goofishOrderChangeLogger.append(row.getId(), row.getAppKey(), row.getOrderNo(),
GoofishOrderChangeLogger.TYPE_SHIP, "AUTO_SHIP", GoofishOrderChangeLogger.TYPE_SHIP, "AUTO_SHIP",
"发货失败 " + (row.getShipError() != null ? row.getShipError() : msg)); "发货失败" + (row.getShipError() != null ? row.getShipError() : msg));
} }
} }
} catch (Exception ex) { } catch (Exception ex) {
@@ -546,7 +546,7 @@ public class GoofishOrderPipeline {
if (goofishOrderChangeLogger != null) { if (goofishOrderChangeLogger != null) {
goofishOrderChangeLogger.append(row.getId(), row.getAppKey(), row.getOrderNo(), goofishOrderChangeLogger.append(row.getId(), row.getAppKey(), row.getOrderNo(),
GoofishOrderChangeLogger.TYPE_SHIP, "AUTO_SHIP", GoofishOrderChangeLogger.TYPE_SHIP, "AUTO_SHIP",
"发货异常 " + (row.getShipError() != null ? row.getShipError() : ex.getMessage())); "发货异常" + (row.getShipError() != null ? row.getShipError() : ex.getMessage()));
} }
log.warn("闲管家发货异常 orderNo={}", row.getOrderNo(), ex); log.warn("闲管家发货异常 orderNo={}", row.getOrderNo(), ex);
} }

View File

@@ -195,7 +195,7 @@ public class ErpGoofishOrderServiceImpl implements IErpGoofishOrderService {
} }
String wb = waybillNo != null ? waybillNo.trim() : ""; String wb = waybillNo != null ? waybillNo.trim() : "";
String sum = summary != null ? summary : ""; String sum = summary != null ? summary : "";
String msg = "jdOrderId=" + jdOrderId + " waybill=" + wb + "" + sum; String msg = "京东订单 " + jdOrderId + ",运单 " + wb + "" + sum;
if (msg.length() > 1000) { if (msg.length() > 1000) {
msg = msg.substring(0, 999) + ""; msg = msg.substring(0, 999) + "";
} }

View File

@@ -824,20 +824,20 @@ public class LogisticsServiceImpl implements ILogisticsService {
// 构建推送消息内容 // 构建推送消息内容
StringBuilder pushContent = new StringBuilder(); StringBuilder pushContent = new StringBuilder();
// 第一行:分销标识(F或PDD // 第一行:分销标识(如 F-闲鱼
String distributionMark = order.getDistributionMark() != null ? order.getDistributionMark() : "未知"; String distributionMark = order.getDistributionMark() != null ? order.getDistributionMark() : "未知";
pushContent.append(distributionMark).append("\n"); pushContent.append(distributionMark).append("\n");
String thirdPartyOrderNo = order.getThirdPartyOrderNo(); String thirdPartyOrderNo = order.getThirdPartyOrderNo();
if (thirdPartyOrderNo != null && !thirdPartyOrderNo.trim().isEmpty()) { if (thirdPartyOrderNo != null && !thirdPartyOrderNo.trim().isEmpty()) {
pushContent.append("第三方单号:").append(thirdPartyOrderNo).append("\n"); pushContent.append("第三方单号:").append(thirdPartyOrderNo.trim()).append("\n");
} }
// 型号 String modelStr = order.getModelNumber() != null ? order.getModelNumber() : "";
pushContent.append("型号:").append(order.getModelNumber() != null ? order.getModelNumber() : "").append("\n"); String addressStr = order.getAddress() != null ? order.getAddress() : "";
// 收货地址 pushContent.append("型号:").append(modelStr).append("\n");
pushContent.append("收货地址:").append(order.getAddress() != null ? order.getAddress() : "").append("\n"); pushContent.append("收货地址:").append(addressStr).append("\n");
// 如果物流链接已更新,在推送消息中说明 // 如果物流链接已更新,在推送消息中说明
if (logisticsLinkUpdated && newLogisticsLink != null && !newLogisticsLink.trim().isEmpty()) { if (logisticsLinkUpdated && newLogisticsLink != null && !newLogisticsLink.trim().isEmpty()) {
pushContent.append("【物流链接已更新】").append("\n"); pushContent.append("【物流链接已更新】").append("\n");
@@ -847,9 +847,23 @@ public class LogisticsServiceImpl implements ILogisticsService {
} }
pushContent.append("\n"); pushContent.append("\n");
} }
// 运单号 // 运单号(首段:冒号后多行留白再写单号,便于复制)
pushContent.append("运单号:").append("\n").append("\n").append("\n").append("\n").append(waybillNo).append("\n"); pushContent.append("运单号:").append("\n").append("\n").append("\n").append("\n").append(waybillNo).append("\n\n\n");
// 闲鱼自动发货段:运单号紧跟在冒号后同一行
pushContent.append("闲鱼自动发货:").append("\n");
String goofishOrderNo;
if (thirdPartyOrderNo != null && !thirdPartyOrderNo.trim().isEmpty()) {
goofishOrderNo = thirdPartyOrderNo.trim();
} else if (order.getOrderId() != null && !order.getOrderId().trim().isEmpty()) {
goofishOrderNo = order.getOrderId().trim();
} else {
goofishOrderNo = "";
}
pushContent.append("单号:").append(goofishOrderNo).append("\n");
pushContent.append("型号:").append(modelStr).append("\n");
pushContent.append("收货地址:").append(addressStr).append("\n");
pushContent.append("运单号:").append(waybillNo).append("\n");
boolean useGoofishWecom = erpGoofishOrderService.hasLinkedGoofishOrder(order.getId()) boolean useGoofishWecom = erpGoofishOrderService.hasLinkedGoofishOrder(order.getId())
|| (distributionMark != null && distributionMark.contains("闲鱼")); || (distributionMark != null && distributionMark.contains("闲鱼"));

View File

@@ -113,11 +113,15 @@ public class WxSendGoofishNotifyClient {
private static String buildContent(String orderNo, String eventType, String source, String message) { private static String buildContent(String orderNo, String eventType, String source, String message) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("【闲鱼订单】").append(orderNo != null ? orderNo : "-").append("\n"); sb.append("【闲鱼订单】").append(orderNo != null ? orderNo : "-").append("\n");
if (StringUtils.hasText(eventType)) { String typeLabel = humanEventType(eventType);
sb.append(eventType); String srcLabel = humanSource(source);
} if (StringUtils.hasText(typeLabel)) {
if (StringUtils.hasText(source)) { sb.append(typeLabel);
sb.append(" | ").append(source); if (StringUtils.hasText(srcLabel)) {
sb.append(" · ").append(srcLabel);
}
} else if (StringUtils.hasText(srcLabel)) {
sb.append(srcLabel);
} }
sb.append("\n"); sb.append("\n");
if (StringUtils.hasText(message)) { if (StringUtils.hasText(message)) {
@@ -130,6 +134,50 @@ public class WxSendGoofishNotifyClient {
return s; return s;
} }
/** 企微展示用,与库内 event_type 枚举一致 */
private static String humanEventType(String eventType) {
if (!StringUtils.hasText(eventType)) {
return "";
}
switch (eventType.trim()) {
case "ORDER_SYNC":
return "订单同步";
case "LOGISTICS_SYNC":
return "物流同步";
case "SHIP":
return "发货";
default:
return eventType.trim();
}
}
/** 企微展示用,与库内 source 一致 */
private static String humanSource(String source) {
if (!StringUtils.hasText(source)) {
return "";
}
switch (source.trim()) {
case "LIST_UPSERT":
return "列表拉单写入";
case "NOTIFY_UPSERT":
return "推送回调写入";
case "LIST":
return "列表摘要";
case "DETAIL_REFRESH":
return "详情刷新";
case "NOTIFY":
return "推送";
case "REDIS_WAYBILL":
return "Redis 运单";
case "AUTO_SHIP":
return "自动发货";
case "JD_LOGISTICS_PUSH":
return "京东物流扫描";
default:
return source.trim();
}
}
/** /**
* 逗号或 | 分隔的 UserID → 企微 API 要求的 user1|user2 * 逗号或 | 分隔的 UserID → 企微 API 要求的 user1|user2
*/ */