This commit is contained in:
雷欧(林平凡)
2025-02-26 15:02:44 +08:00
parent 5b0ea491a5
commit d8c3450426
2 changed files with 127 additions and 22 deletions

View File

@@ -4,6 +4,7 @@ package cn.van.business.util;
import cn.van.business.model.jd.OrderRow;
import cn.van.business.repository.OrderRowRepository;
import com.alibaba.fastjson2.util.DateUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jd.open.api.sdk.DefaultJdClient;
import com.jd.open.api.sdk.JdClient;
import com.jd.open.api.sdk.domain.kplunion.OrderService.request.query.OrderRowReq;
@@ -29,10 +30,8 @@ import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -77,9 +76,14 @@ public class JDUtil {
private final OrderRowRepository orderRowRepository;
private final WXUtil wxUtil;
private final OrderUtil orderUtil;
// 在类中添加以下字段
private final StringRedisTemplate redisTemplate;
private static final String INTERACTION_STATE_PREFIX = "interaction_state:";
private static final long TIMEOUT_MINUTES = 1;
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 通过构造函数注入所有依赖项Spring将自动注入这些依赖
@Autowired // @Autowired 在构造函数上可以省略,如果类只有一个构造函数
// 构造函数注入StringRedisTemplate
@Autowired
public JDUtil(StringRedisTemplate redisTemplate, OrderRowRepository orderRowRepository, WXUtil wxUtil, OrderUtil orderUtil) {
this.redisTemplate = redisTemplate;
this.orderRowRepository = orderRowRepository;
@@ -87,6 +91,27 @@ public class JDUtil {
this.orderUtil = orderUtil;
}
// 定义一个内部类来存储用户交互状态
@Getter
@Setter
private static class UserInteractionState {
private String lastInteractionTime;
private String currentState;
public UserInteractionState() {
this.lastInteractionTime = LocalDateTime.now().format(DATE_TIME_FORMATTER);
this.currentState = "INIT";
}
public void updateLastInteractionTime() {
this.lastInteractionTime = LocalDateTime.now().format(DATE_TIME_FORMATTER);
}
}
// 添加ObjectMapper来序列化和反序列化UserInteractionState
private final ObjectMapper objectMapper = new ObjectMapper();
/**
* 将 响应参数转化为 OrderRow并返回
*/
@@ -181,7 +206,7 @@ public class JDUtil {
/**
* 实时刷新最近10分钟的订单
*/
@Scheduled(cron = "0 * * * * ?") // 每分钟执行一次
@Scheduled(cron = "0 * * * * ?")
public void fetchLatestOrder() {
LocalDateTime now = LocalDateTime.now();
LocalDateTime lastMinute = now.minusMinutes(10).withSecond(0).withNano(0);
@@ -602,6 +627,8 @@ public class JDUtil {
* 接收京粉指令指令
*/
public void sendOrderToWxByOrderJD(String order, String fromWxid) {
if ("消毒柜".equals(order)) { handleUserInteraction(fromWxid, order); return; }
int[] param = {-1};
WXUtil.SuperAdmin superAdmin = super_admins.get(fromWxid);
String unionId = superAdmin.getUnionId();
@@ -641,6 +668,7 @@ public class JDUtil {
content.append("京高级违规+整数\r");
content.append("京高级+订单号\r\"");
content.append("京高级SKU+sku\\r\"");
content.append("京高级搜索+搜索标题只返回最近10条\r\"");
break;
case "测试指令": {
//test01();
@@ -672,19 +700,7 @@ public class JDUtil {
break;
}
case "昨日统计": {
List<OrderRow> yesterdayOrders = filterOrdersByDate(orderRows, 1);
List<OrderRow> todayOrders = filterOrdersByDate(orderRows, 0);
yesterdayOrders.removeAll(todayOrders);
content.append("昨日统计:\n");
content.append("订单总数:").append(yesterdayOrders.size()).append("\r");
content.append("已付款:").append(yesterdayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).count()).append("\r");
content.append("已取消:").append(yesterdayOrders.stream().filter(orderRow -> orderRow.getValidCode() != 16 && orderRow.getValidCode() != 17).count()).append("\r");
content.append("已完成:").append(yesterdayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 17).count()).append("\r");
content.append("违规:").append(getStreamForWeiGui(yesterdayOrders).count()).append("\r");
content.append("已付款佣金:").append(yesterdayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).mapToDouble(OrderRow::getEstimateFee).sum()).append("\r");
content.append("已完成佣金:").append(yesterdayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 17).mapToDouble(OrderRow::getEstimateFee).sum());
content.append("\r" + "违规佣金:").append(getStreamForWeiGui(yesterdayOrders).mapToDouble(orderRow -> orderRow.getEstimateCosPrice() * orderRow.getCommissionRate() * 0.01).sum());
break;
}
case "三日统计": {
List<OrderRow> last3DaysOrders = filterOrdersByDate(orderRows, 3);
@@ -1128,4 +1144,93 @@ public class JDUtil {
private Long orderId;
private Date orderDate;
}
/**
*
* 消毒柜部分的业务逻辑
*
*
* */
@Scheduled(fixedRate = 60000) // 每分钟执行一次
public void cleanUpTimeoutStates() {
LocalDateTime now = LocalDateTime.now();
Objects.requireNonNull(redisTemplate.keys(INTERACTION_STATE_PREFIX + "*")).forEach(key -> {
String stateJson = redisTemplate.opsForValue().get(key);
try {
UserInteractionState state = objectMapper.readValue(stateJson, UserInteractionState.class);
LocalDateTime lastInteractionTime = LocalDateTime.parse(state.getLastInteractionTime(), DATE_TIME_FORMATTER);
if (ChronoUnit.MINUTES.between(lastInteractionTime, now) > TIMEOUT_MINUTES) {
redisTemplate.delete(key);
}
} catch (Exception e) {
logger.error("Error parsing interaction state: " + e.getMessage());
}
});
}
public void handleUserInteraction(String fromWxid, String message) {
String key = INTERACTION_STATE_PREFIX + fromWxid;
String stateJson = redisTemplate.opsForValue().get(key);
UserInteractionState state;
if (stateJson == null) {
state = new UserInteractionState();
} else {
try {
state = objectMapper.readValue(stateJson, UserInteractionState.class);
// 检查是否超时
LocalDateTime now = LocalDateTime.now();
LocalDateTime lastInteractionTime = LocalDateTime.parse(state.getLastInteractionTime(), DATE_TIME_FORMATTER);
if (ChronoUnit.MINUTES.between(lastInteractionTime, now) > TIMEOUT_MINUTES) {
redisTemplate.delete(key);
state = new UserInteractionState();
}
} catch (Exception e) {
logger.error("Error parsing interaction state: " + e.getMessage());
state = new UserInteractionState();
}
}
state.updateLastInteractionTime();
switch (state.getCurrentState()) {
case "INIT":
if ("消毒柜".equals(message)) {
wxUtil.sendTextMessage(fromWxid, "1查询消毒柜订单2输入新的订单3修改订单", 1, fromWxid);
state.setCurrentState("DISINFECTANT_CABINET");
}
break;
case "DISINFECTANT_CABINET":
switch (message) {
case "1":
// 查询消毒柜订单的逻辑
wxUtil.sendTextMessage(fromWxid, "查询消毒柜订单的逻辑", 1, fromWxid);
state.setCurrentState("INIT");
break;
case "2":
// 输入新的订单的逻辑
wxUtil.sendTextMessage(fromWxid, "输入新的订单的逻辑", 1, fromWxid);
state.setCurrentState("INIT");
break;
case "3":
// 修改订单的逻辑
wxUtil.sendTextMessage(fromWxid, "修改订单的逻辑", 1, fromWxid);
state.setCurrentState("INIT");
break;
default:
wxUtil.sendTextMessage(fromWxid, "无效的选择,请重新选择", 1, fromWxid);
break;
}
break;
default:
wxUtil.sendTextMessage(fromWxid, "无效的状态,请重新开始对话", 1, fromWxid);
state.setCurrentState("INIT");
break;
}
try {
redisTemplate.opsForValue().set(key, objectMapper.writeValueAsString(state), TIMEOUT_MINUTES, TimeUnit.MINUTES);
} catch (Exception e) {
logger.error("Error saving interaction state: " + e.getMessage());
}
}
}

View File

@@ -191,7 +191,7 @@ public class WxMessageConsumer {
//}
private static String getUrlStr(String msg) {
//String urlPattern = "https?://[\\w-\\.]+(\\.[a-z]{2,})?(/[\\w-./?%&=]*)?"
String urlPattern = "https?://[^\\s]+?\\.(html|htm)(\\?[^\\s]*?)?";
String urlPattern = "https?://\\S+?\\.(html|htm)(\\?\\S*?)?";
Pattern pattern = Pattern.compile(urlPattern);
Matcher matcher = pattern.matcher(msg);
@@ -207,7 +207,7 @@ public class WxMessageConsumer {
// 移除最后一个字符(即问号)
finallyUrl = finallyUrl.substring(0, finallyUrl.length() - 1);
}
if (finallyUrl.contains("item.m.jd.com/product")) {
if (finallyUrl != null && finallyUrl.contains("item.m.jd.com/product")) {
finallyUrl = finallyUrl.replace("item.m.jd.com/product", "item.jd.com");
}
return finallyUrl;