This commit is contained in:
2025-09-27 19:27:44 +08:00
parent eb969db392
commit e5961bba23

View File

@@ -17,7 +17,9 @@ import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.concurrent.TimeUnit;
/**
@@ -37,25 +39,7 @@ public class InstructionServiceImpl implements IInstructionService {
private StringRedisTemplate stringRedisTemplate;
// 录单模板(与 jd/JDUtil 中 WENAN_D 保持一致)
private static final String WENAN_D = "单:\n" +
"{单号} \n备注{单的备注}\n" +
"分销标记:{分销标记}\n" +
"型号:\n" +
"{型号}\n" +
"链接:\n" +
"{链接}\n" +
"下单付款:\n" +
"\n" +
"后返金额:\n" +
"\n" +
"地址:\n" +
"{地址}\n" +
"物流链接:\n" +
"\n" +
"订单号:\n" +
"\n" +
"下单人:\n" +
"\n";
private static final String WENAN_D = "单:\n" + "{单号} \n备注{单的备注}\n" + "分销标记:{分销标记}\n" + "型号:\n" + "{型号}\n" + "链接:\n" + "{链接}\n" + "下单付款:\n" + "\n" + "后返金额:\n" + "\n" + "地址:\n" + "{地址}\n" + "物流链接:\n" + "\n" + "订单号:\n" + "\n" + "下单人:\n" + "\n";
@Override
public List<String> execute(String command) {
@@ -102,19 +86,32 @@ public class InstructionServiceImpl implements IInstructionService {
if (all == null) all = Collections.emptyList();
switch (action) {
case "今日统计": return statsText(filterByDays(all, 0), "今日统计");
case "昨日统计": return statsText(filterYesterday(all), "日统计");
case "日统计": return statsText(filterByRange(all, 3), "三日统计");
case "七日统计": return statsText(filterByRange(all, 7), "日统计");
case "一个月统计": return statsText(filterByRange(all, 30), "一个月统计");
case "两个月统计": return statsText(filterByRange(all, 60), "两个月统计");
case "三个月统计": return statsText(filterByRange(all, 90), "三个月统计");
case "这个月统计": return statsText(filterThisMonth(all), "这个月统计");
case "个月统计": return statsText(filterLastMonth(all), "上个月统计");
case "总统计": return statsText(all, "统计");
case "今日订单": return listOrders(filterByDays(all, 0), "今日订单");
case "昨日订单": return listOrders(filterYesterday(all), "昨日订单");
case "七日订单": return listOrders(filterByRange(all, 7), "七日订单");
case "今日统计":
return statsText(filterByDays(all, 0), "日统计");
case "日统计":
return statsText(filterYesterday(all), "日统计");
case "三日统计":
return statsText(filterByRange(all, 3), "三日统计");
case "七日统计":
return statsText(filterByRange(all, 7), "七日统计");
case "个月统计":
return statsText(filterByRange(all, 30), "一个月统计");
case "两个月统计":
return statsText(filterByRange(all, 60), "两个月统计");
case "三个月统计":
return statsText(filterByRange(all, 90), "三个月统计");
case "这个月统计":
return statsText(filterThisMonth(all), "这个月统计");
case "上个月统计":
return statsText(filterLastMonth(all), "上个月统计");
case "总统计":
return statsText(all, "总统计");
case "今日订单":
return listOrders(filterByDays(all, 0), "今日订单");
case "昨日订单":
return listOrders(filterYesterday(all), "昨日订单");
case "七日订单":
return listOrders(filterByRange(all, 7), "七日订单");
default:
// 高级命令违规N、SKU、搜索、JF… 此处按需扩展
if (action.startsWith("高级")) {
@@ -132,27 +129,13 @@ public class InstructionServiceImpl implements IInstructionService {
List<JDOrder> list = jdOrderService.selectJDOrderList(new JDOrder());
if (list == null) list = Collections.emptyList();
String low = kw.toLowerCase(Locale.ROOT);
List<JDOrder> matched = list.stream().filter(o ->
contains(o.getRemark(), low) || contains(o.getOrderId(), low) || contains(o.getModelNumber(), low) || contains(o.getAddress(), low) || contains(o.getBuyer(), low)
).limit(50).collect(Collectors.toList());
List<JDOrder> matched = list.stream().filter(o -> contains(o.getRemark(), low) || contains(o.getOrderId(), low) || contains(o.getModelNumber(), low) || contains(o.getAddress(), low) || contains(o.getBuyer(), low)).limit(50).collect(Collectors.toList());
if (matched.isEmpty()) return Collections.singletonList("未找到匹配的订单");
StringBuilder sb = new StringBuilder();
int i = 0;
for (JDOrder o : matched) {
i++;
sb.append(i).append(", 单:").append(nvl(o.getRemark()))
.append("\n分销标记").append(nvl(o.getDistributionMark()))
.append("\n型号").append(nvl(o.getModelNumber()))
.append("\n链接").append(nvl(o.getLink()))
.append("\n下单付款").append(nvl(o.getPaymentAmount()))
.append("\n后返金额").append(nvl(o.getRebateAmount()))
.append("\n地址").append(nvl(o.getAddress()))
.append("\n物流链接").append(nvl(o.getLogisticsLink()))
.append("\n订单号").append(nvl(o.getOrderId()))
.append("\n下单人").append(nvl(o.getBuyer()))
.append("\n下单时间").append(nvl(o.getOrderTime()))
.append("\n备注").append(nvl(o.getStatus()))
.append("\n━━━━━━━━━━━━\n");
sb.append(i).append(", 单:").append(nvl(o.getRemark())).append("\n分销标记").append(nvl(o.getDistributionMark())).append("\n型号").append(nvl(o.getModelNumber())).append("\n链接").append(nvl(o.getLink())).append("\n下单付款").append(nvl(o.getPaymentAmount())).append("\n后返金额").append(nvl(o.getRebateAmount())).append("\n地址").append(nvl(o.getAddress())).append("\n物流链接").append(nvl(o.getLogisticsLink())).append("\n订单号").append(nvl(o.getOrderId())).append("\n下单人").append(nvl(o.getBuyer())).append("\n下单时间").append(nvl(o.getOrderTime())).append("\n备注").append(nvl(o.getStatus())).append("\n━━━━━━━━━━━━\n");
}
return Collections.singletonList(sb.toString());
}
@@ -173,17 +156,7 @@ public class InstructionServiceImpl implements IInstructionService {
List<JDOrder> sorted = filtered.stream().sorted(Comparator.comparing(JDOrder::getRemark, Comparator.nullsFirst(String::compareTo))).collect(Collectors.toList());
StringBuilder sb = new StringBuilder();
for (JDOrder o : sorted) {
sb.append(nvl(o.getRemark())).append('\t')
.append(nvl(o.getOrderId())).append('\t')
.append(fmt(o.getOrderTime()).split(" ")[0]).append('\t')
.append(nvl(o.getModelNumber())).append('\t')
.append(nvl(o.getAddress())).append('\t')
.append(nvl(o.getLogisticsLink())).append('\t')
.append('\t').append(nvl(o.getBuyer())).append('\t')
.append(nvl(o.getPaymentAmount())).append('\t')
.append(nvl(o.getRebateAmount())).append('\t')
.append(mapDistribution(o.getDistributionMark())).append('\t')
.append(nvl(o.getStatus())).append("\n");
sb.append(nvl(o.getRemark())).append('\t').append(nvl(o.getOrderId())).append('\t').append(fmt(o.getOrderTime()).split(" ")[0]).append('\t').append(nvl(o.getModelNumber())).append('\t').append(nvl(o.getAddress())).append('\t').append(nvl(o.getLogisticsLink())).append('\t').append('\t').append(nvl(o.getBuyer())).append('\t').append(nvl(o.getPaymentAmount())).append('\t').append(nvl(o.getRebateAmount())).append('\t').append(mapDistribution(o.getDistributionMark())).append('\t').append(nvl(o.getStatus())).append("\n");
}
return Collections.singletonList(sb.toString());
}
@@ -201,9 +174,7 @@ public class InstructionServiceImpl implements IInstructionService {
List<JDOrder> filtered = list.stream().filter(o -> o.getOrderTime() != null && !o.getOrderTime().before(start) && !o.getOrderTime().after(end)).collect(Collectors.toList());
if (filtered.isEmpty()) return Collections.singletonList("今天没有订单。");
Map<String, List<JDOrder>> byDM = filtered.stream()
.filter(o -> o.getStatus() == null || !"拍错退款".equals(o.getStatus()))
.collect(Collectors.groupingBy(JDOrder::getDistributionMark));
Map<String, List<JDOrder>> byDM = filtered.stream().filter(o -> o.getStatus() == null || !"拍错退款".equals(o.getStatus())).collect(Collectors.groupingBy(JDOrder::getDistributionMark));
List<String> outputs = new ArrayList<>();
List<Map.Entry<String, List<JDOrder>>> dmEntries = new ArrayList<>(byDM.entrySet());
dmEntries.sort(Comparator.comparing(en -> en.getKey() == null ? "" : en.getKey()));
@@ -219,8 +190,7 @@ public class InstructionServiceImpl implements IInstructionService {
for (Map.Entry<String, Long> em : modelEntries) {
int c = em.getValue().intValue();
totalCount += c;
summary.append("型号:").append(em.getKey() != null ? em.getKey() : "未知")
.append(" 数量:").append(c).append("\n");
summary.append("型号:").append(em.getKey() != null ? em.getKey() : "未知").append(" 数量:").append(c).append("\n");
}
summary.append("总计:").append(totalCount).append("\n详情");
@@ -230,17 +200,10 @@ public class InstructionServiceImpl implements IInstructionService {
for (JDOrder o : sorted) {
if ("拍错退款".equals(o.getStatus())) continue;
idx++;
detail.append("\n").append(idx).append(" ────────────\n")
.append("单:").append(o.getRemark() != null ? o.getRemark() : "未提供")
.append("\n备注").append(o.getStatus() != null ? o.getStatus() : " ")
.append("\n型号").append(o.getModelNumber() != null ? o.getModelNumber() : "未提供")
.append("\n地址").append(o.getAddress() != null ? o.getAddress() : "未提供")
.append("\n物流链接\n").append(o.getLogisticsLink() != null ? o.getLogisticsLink() : "");
detail.append("\n").append(idx).append(" ────────────\n").append("单:").append(o.getRemark() != null ? o.getRemark() : "未提供").append("\n备注").append(o.getStatus() != null ? o.getStatus() : " ").append("\n型号").append(o.getModelNumber() != null ? o.getModelNumber() : "未提供").append("\n地址").append(o.getAddress() != null ? o.getAddress() : "未提供").append("\n物流链接\n").append(o.getLogisticsLink() != null ? o.getLogisticsLink() : "");
}
StringBuilder single = new StringBuilder();
single.append("分销标记:").append(dm).append("\n")
.append(summary)
.append(detail).append("\n");
single.append("分销标记:").append(dm).append("\n").append(summary).append(detail).append("\n");
outputs.add(single.toString().trim());
}
return outputs.isEmpty() ? Collections.singletonList("无数据") : outputs;
@@ -253,6 +216,7 @@ public class InstructionServiceImpl implements IInstructionService {
// ===== TF/H/生 处理 =====
private static final HashMap<String, String> productWithJF = new HashMap<>();
static {
/**
* 130
@@ -270,17 +234,21 @@ public class InstructionServiceImpl implements IInstructionService {
productWithJF.put("ZQD180F-EB200", "https://u.jd.com/SDBkTJg");
productWithJF.put("CXW-298-IQ92DPRO", "https://u.jd.com/SrWlqkb");
}
private static final List<String> phoneWithTF = new ArrayList<>();
static {
/*
18539187615
15738558087
13243039070
15639125541
18539187615
15738558087 */
phoneWithTF.add("13243039070");
phoneWithTF.add("15639125541");
17530176250 */
phoneWithTF.add("18539187615");
phoneWithTF.add("15738558087");
phoneWithTF.add("13243039070");
phoneWithTF.add("15639125541");
phoneWithTF.add("17530176250");
}
private String handleTF(String input) {
@@ -341,12 +309,8 @@ public class InstructionServiceImpl implements IInstructionService {
String fullAddress = cleanedAddress + " 安装派送联系" + phone + (suffix.isEmpty() ? "" : "" + suffix);
StringBuilder sheng = new StringBuilder();
sheng.append("\n")
.append("H\n")
.append(modelNumber).append("\n")
.append("\n") // 转链链接留空
.append("1\n")
.append(name).append(fullAddress);
sheng.append("\n").append("H\n").append(modelNumber).append("\n").append("\n") // 转链链接留空
.append("1\n").append(name).append(fullAddress);
return generateOrderText(sheng.toString());
}
@@ -373,7 +337,10 @@ public class InstructionServiceImpl implements IInstructionService {
String model = split[2].trim();
String link = split[3].trim();
int num = 1;
try { num = Integer.parseInt(split[4].trim()); } catch (Exception ignore) {}
try {
num = Integer.parseInt(split[4].trim());
} catch (Exception ignore) {
}
String address = split[5].trim();
// 与 JDUtil 一致:地址 24 小时去重校验(白名单放行)
@@ -422,20 +389,14 @@ public class InstructionServiceImpl implements IInstructionService {
startCount = count + 1;
int endCount = count + total;
stringRedisTemplate.opsForValue().set(redisKey, String.valueOf(endCount), 1, TimeUnit.DAYS);
} catch (Exception ignore) {}
} catch (Exception ignore) {
}
}
for (int i = 0; i < total; i++) {
int currentCount = startCount + i;
String orderId = today + String.format("%03d", currentCount);
String current = WENAN_D
.replace("{单号}", orderId)
.replace("{单的备注}", remark)
.replace("{分销标记}", fenxiao)
.replace("{链接}", link)
.replace("{地址}", address)
.replace("{型号}", model)
.replaceAll("[|]", "");
String current = WENAN_D.replace("{单号}", orderId).replace("{单的备注}", remark).replace("{分销标记}", fenxiao).replace("{链接}", link).replace("{地址}", address).replace("{型号}", model).replaceAll("[|]", "");
out.append(current);
if (i < total - 1) out.append("\n");
}
@@ -448,7 +409,8 @@ public class InstructionServiceImpl implements IInstructionService {
}
private String extractBetweenBrackets(String s) {
int a = s.indexOf('['); int b = s.indexOf(']');
int a = s.indexOf('[');
int b = s.indexOf(']');
if (a != -1 && b != -1 && b > a) return s.substring(a + 1, b);
return "";
}
@@ -540,21 +502,14 @@ public class InstructionServiceImpl implements IInstructionService {
else if (order.getDistributionMark().startsWith("F")) distributionMark2 = "";
}
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
sb.append(order.getRemark()).append('\t')
.append(order.getOrderId()).append('\t')
.append(sdf.format(order.getOrderTime())).append('\t')
.append(order.getModelNumber()).append('\t')
.append(order.getAddress()).append('\t')
.append(order.getLogisticsLink()).append('\t')
.append('\t').append(order.getBuyer()).append('\t')
.append(nvl(order.getPaymentAmount())).append('\t')
.append(nvl(order.getRebateAmount())).append('\t')
.append(distributionMark2);
sb.append(order.getRemark()).append('\t').append(order.getOrderId()).append('\t').append(sdf.format(order.getOrderTime())).append('\t').append(order.getModelNumber()).append('\t').append(order.getAddress()).append('\t').append(order.getLogisticsLink()).append('\t').append('\t').append(order.getBuyer()).append('\t').append(nvl(order.getPaymentAmount())).append('\t').append(nvl(order.getRebateAmount())).append('\t').append(distributionMark2);
return info + "\n" + sb;
}
private boolean isEmpty(String s) { return s == null || s.isEmpty(); }
private boolean isEmpty(String s) {
return s == null || s.isEmpty();
}
// 参照 JDUtil.parseOrderFromText
private JDOrder parseOrderFromText(String input) {
@@ -582,8 +537,14 @@ public class InstructionServiceImpl implements IInstructionService {
order.setModelNumber(fields.getOrDefault("型号", null));
order.setLink(fields.getOrDefault("链接", null));
order.setStatus(fields.getOrDefault("备注", null));
try { order.setPaymentAmount(Double.parseDouble(fields.getOrDefault("下单付款", "0"))); } catch (Exception ignore) {}
try { order.setRebateAmount(Double.parseDouble(fields.getOrDefault("后返金额", "0"))); } catch (Exception ignore) {}
try {
order.setPaymentAmount(Double.parseDouble(fields.getOrDefault("下单付款", "0")));
} catch (Exception ignore) {
}
try {
order.setRebateAmount(Double.parseDouble(fields.getOrDefault("后返金额", "0")));
} catch (Exception ignore) {
}
order.setAddress(fields.getOrDefault("地址", null));
order.setLogisticsLink(extractFirstUrl(fields.getOrDefault("物流链接", "")));
order.setOrderId(fields.getOrDefault("订单号", null));
@@ -592,7 +553,9 @@ public class InstructionServiceImpl implements IInstructionService {
String dateStr = fields.getOrDefault("", "").split(" ")[0];
java.text.SimpleDateFormat sdf2 = new java.text.SimpleDateFormat("yyyy-MM-dd");
order.setOrderTime(sdf2.parse(dateStr));
} catch (Exception e) { order.setOrderTime(new Date()); }
} catch (Exception e) {
order.setOrderTime(new Date());
}
return order;
}
@@ -631,24 +594,7 @@ public class InstructionServiceImpl implements IInstructionService {
double violationCommission = rows.stream().filter(o -> o.getValidCode() != null && (o.getValidCode() == 13 || o.getValidCode() == 25 || o.getValidCode() == 26 || o.getValidCode() == 27 || o.getValidCode() == 28 || o.getValidCode() == 29) && o.getEstimateCosPrice() != null && o.getCommissionRate() != null).mapToDouble(o -> o.getEstimateCosPrice() * o.getCommissionRate() * 0.01).sum();
StringBuilder sb = new StringBuilder();
sb.append("* ").append(title).append(" *\n")
.append("━━━━━━━━━━━━\n")
.append("订单总数:").append(total).append("\n")
.append("有效订单:").append(total - canceled).append("\n")
.append("已取消:").append(canceled).append("\n")
.append("────────────\n")
.append("已付款:").append(paid).append("\n")
.append("已付款佣金:").append(fmt(paidCommission)).append("\n")
.append("────────────\n")
.append("待付款:").append(pending).append("\n")
.append("待付款佣金:").append(fmt(pendingCommission)).append("\n")
.append("────────────\n")
.append("已完成:").append(completed).append("\n")
.append("已完成佣金:").append(fmt(completedCommission)).append("\n")
.append("────────────\n")
.append("违规订单:").append(violation).append("\n")
.append("违规佣金:").append(fmt(violationCommission)).append("\n")
.append("━━━━━━━━━━━━");
sb.append("* ").append(title).append(" *\n").append("━━━━━━━━━━━━\n").append("订单总数:").append(total).append("\n").append("有效订单:").append(total - canceled).append("\n").append("已取消:").append(canceled).append("\n").append("────────────\n").append("已付款:").append(paid).append("\n").append("已付款佣金:").append(fmt(paidCommission)).append("\n").append("────────────\n").append("待付款:").append(pending).append("\n").append("待付款佣金:").append(fmt(pendingCommission)).append("\n").append("────────────\n").append("已完成:").append(completed).append("\n").append("已完成佣金:").append(fmt(completedCommission)).append("\n").append("────────────\n").append("违规订单:").append(violation).append("\n").append("违规佣金:").append(fmt(violationCommission)).append("\n").append("━━━━━━━━━━━━");
return sb.toString();
}
@@ -659,10 +605,7 @@ public class InstructionServiceImpl implements IInstructionService {
int i = 0;
for (OrderRows r : rows) {
i++;
sb.append(i).append(". ").append(Optional.ofNullable(r.getSkuName()).orElse("-"))
.append(" | 订单号:").append(Optional.ofNullable(r.getOrderId()).map(String::valueOf).orElse("-"))
.append(" | 时间:").append(fmt(r.getOrderTime()))
.append(" | 有效:").append(r.getValidCode()==null?"-":r.getValidCode()).append("\n");
sb.append(i).append(". ").append(Optional.ofNullable(r.getSkuName()).orElse("-")).append(" | 订单号:").append(Optional.ofNullable(r.getOrderId()).map(String::valueOf).orElse("-")).append(" | 时间:").append(fmt(r.getOrderTime())).append(" | 有效:").append(r.getValidCode() == null ? "-" : r.getValidCode()).append("\n");
if (i >= 100) break; // 最多100条
}
return sb.toString();
@@ -687,7 +630,8 @@ public class InstructionServiceImpl implements IInstructionService {
private List<OrderRows> filterYesterday(List<OrderRows> list) {
LocalDate y = LocalDate.now().minusDays(1);
return list.stream().filter(o -> {
Date d = o.getOrderTime(); if (d==null) return false;
Date d = o.getOrderTime();
if (d == null) return false;
LocalDate od = d.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
return od.equals(y);
}).collect(Collectors.toList());
@@ -696,7 +640,8 @@ public class InstructionServiceImpl implements IInstructionService {
private List<OrderRows> filterThisMonth(List<OrderRows> list) {
LocalDate now = LocalDate.now();
return list.stream().filter(o -> {
Date d = o.getOrderTime(); if (d==null) return false;
Date d = o.getOrderTime();
if (d == null) return false;
LocalDate od = d.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
return od.getYear() == now.getYear() && od.getMonth() == now.getMonth();
}).collect(Collectors.toList());
@@ -705,7 +650,8 @@ public class InstructionServiceImpl implements IInstructionService {
private List<OrderRows> filterLastMonth(List<OrderRows> list) {
LocalDate now = LocalDate.now().minusMonths(1);
return list.stream().filter(o -> {
Date d = o.getOrderTime(); if (d==null) return false;
Date d = o.getOrderTime();
if (d == null) return false;
LocalDate od = d.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
return od.getYear() == now.getYear() && od.getMonth() == now.getMonth();
}).collect(Collectors.toList());
@@ -714,31 +660,12 @@ public class InstructionServiceImpl implements IInstructionService {
// ===== 工具 =====
private String jingMenu() {
StringBuilder content = new StringBuilder();
content.append("菜单:京+命令,如: 京今日统计\r\n")
.append("今日统计\r\n")
.append("昨日统计\r\n")
.append("七日统计\r\n")
.append("一个月统计\r\n")
.append("两个月统计\r\n")
.append("三个月统计\r\n")
.append("总统计\r\n")
.append("这个月统计\r\n")
.append("上个月统计\r\n")
.append("\r\n")
.append("今日订单\r\n")
.append("昨日订单\r\n")
.append("七日订单\r\n");
content.append("菜单:京+命令,如: 京今日统计\r\n").append("今日统计\r\n").append("昨日统计\r\n").append("七日统计\r\n").append("一个月统计\r\n").append("两个月统计\r\n").append("三个月统计\r\n").append("总统计\r\n").append("这个月统计\r\n").append("上个月统计\r\n").append("\r\n").append("今日订单\r\n").append("昨日订单\r\n").append("七日订单\r\n");
return content.toString();
}
private String helpText() {
return "可用指令示例:\n"
+ "1) 京菜单(查看所有可用命令)\n"
+ "2) 京今日统计 / 京昨日统计 / 京七日统计 / 京一个月统计 等\n"
+ "3) 京今日订单 / 京昨日订单 / 京七日订单\n"
+ "4) 慢搜 关键词 / 慢查 关键词(从录单库模糊查询)\n"
+ "5) 录单20250101-20250107 或 录单昨日|三日|七日(仅查询导出)\n"
+ "\n提示转链与礼金请前往一键转链页面使用。";
return "可用指令示例:\n" + "1) 京菜单(查看所有可用命令)\n" + "2) 京今日统计 / 京昨日统计 / 京七日统计 / 京一个月统计 等\n" + "3) 京今日订单 / 京昨日订单 / 京七日订单\n" + "4) 慢搜 关键词 / 慢查 关键词(从录单库模糊查询)\n" + "5) 录单20250101-20250107 或 录单昨日|三日|七日(仅查询导出)\n" + "\n提示转链与礼金请前往一键转链页面使用。";
}
private LocalDateTime effectiveToday() {