This commit is contained in:
Leo
2025-12-14 14:50:49 +08:00
parent c661e921df
commit 2fd371f2f4

View File

@@ -1478,124 +1478,215 @@ public class InstructionServiceImpl implements IInstructionService {
return null; return null;
} }
// 参照 JDUtil.parseOrderFromText // 参照 JDUtil.parseOrderFromText,适配新模板格式
private JDOrder parseOrderFromText(String input) { private JDOrder parseOrderFromText(String input) {
// 不要替换所有空格,保留换行符用于正确解析 // 不清理空白字符,保持原始格式以便正确解析多行字段
Map<String, String> fields = new HashMap<>(); Map<String, String> fields = new HashMap<>();
// 先尝试新格式(带第三方单号和京粉实际价格 // 检查是否是新格式(包含"下单链接(必须用这个):"或"下单地址(注意带分机):"
extractField(input, fields, "单:", "备注"); boolean isNewFormat = input.contains("下单链接(必须用这个):") || input.contains("下单地址(注意带分机)");
extractField(input, fields, "备注:", "分销标记:");
// 检查是否有"第三方单号:"字段,如果没有则是旧格式 if (isNewFormat) {
boolean hasThirdPartyOrderNo = input.contains("第三方单号:"); // 新格式:使用新的字段标签和分隔线
boolean hasJingfenPrice = input.contains("京粉实际价格"); extractFieldWithSeparator(input, fields, "单:", "分销标记");
extractFieldWithSeparator(input, fields, "分销标记:", "第三方单号:");
extractFieldWithSeparator(input, fields, "第三方单号:", "下单链接(必须用这个):");
extractFieldWithSeparator(input, fields, "下单链接(必须用这个):", "下单地址(注意带分机):");
extractFieldWithSeparator(input, fields, "下单地址(注意带分机):", "型号:");
extractFieldWithSeparator(input, fields, "型号:", "下单人(需填):");
extractFieldWithSeparator(input, fields, "下单人(需填):", "下单付款(注意核对):");
extractFieldWithSeparator(input, fields, "下单付款(注意核对):", "后返金额(注意核对):");
extractFieldWithSeparator(input, fields, "后返金额(注意核对):", "订单号(需填):");
extractFieldWithSeparator(input, fields, "订单号(需填):", "物流链接(需填):");
extractFieldWithSeparator(input, fields, "物流链接(需填):", "备注(下单号码有变动/没法带分机号的写这里):");
if (hasThirdPartyOrderNo) { // 手动提取"备注"字段(最后一个字段,可能后面有分隔线或"京粉实际价格"
// 新格式:有第三方单号字段 java.util.regex.Pattern remarkPattern = java.util.regex.Pattern.compile("备注(下单号码有变动/没法带分机号的写这里):[\\s\\n]*([\\s\\S]*?)[\\s\\n]*(?=—————————|京粉实际价格|\\Z)", java.util.regex.Pattern.DOTALL);
extractField(input, fields, "分销标记:", "第三方单号:"); java.util.regex.Matcher remarkMatcher = remarkPattern.matcher(input);
extractField(input, fields, "第三方单号:", "型号:"); if (remarkMatcher.find()) {
} else { String remarkValue = remarkMatcher.group(1);
// 旧格式:分销标记后面直接是型号 if (remarkValue != null) {
extractField(input, fields, "分销标记:", "型号:"); remarkValue = remarkValue.trim();
} // 去掉可能的分隔线
remarkValue = remarkValue.replaceAll("^—————————[\\s\\n]*", "").trim();
extractField(input, fields, "型号:", "链接:"); if (!remarkValue.isEmpty()) {
extractField(input, fields, "链接:", "下单付款:"); fields.put("备注", remarkValue);
extractField(input, fields, "下单付款:", "后返金额:"); }
extractField(input, fields, "后返金额:", "地址:"); }
extractField(input, fields, "地址:", "物流链接:"); }
extractField(input, fields, "物流链接:", "订单号:");
extractField(input, fields, "订单号:", "下单人:");
// 京粉实际价格不从表单解析,而是从数据库查询获取
// 如果表单中有这个字段,也提取出来(但不会使用,仅用于兼容)
if (hasJingfenPrice) {
extractField(input, fields, "下单人:", "京粉实际价格:");
extractField(input, fields, "京粉实际价格:", "");
} else { } else {
// 旧格式:兼容旧模板
extractField(input, fields, "单:", "备注:");
extractField(input, fields, "备注:", "分销标记:");
boolean hasThirdPartyOrderNo = input.contains("第三方单号:");
if (hasThirdPartyOrderNo) {
extractField(input, fields, "分销标记:", "第三方单号:");
extractField(input, fields, "第三方单号:", "型号:");
} else {
extractField(input, fields, "分销标记:", "型号:");
}
extractField(input, fields, "型号:", "链接:");
extractField(input, fields, "链接:", "下单付款:");
extractField(input, fields, "下单付款:", "后返金额:");
extractField(input, fields, "后返金额:", "地址:");
extractField(input, fields, "地址:", "物流链接:");
extractField(input, fields, "物流链接:", "订单号:");
extractField(input, fields, "订单号:", "下单人:");
extractField(input, fields, "下单人:", ""); extractField(input, fields, "下单人:", "");
} }
// 使用正则提取下单人(兼容新旧格式)
String nextField = hasJingfenPrice ? "京粉实际价格:" : "单:";
java.util.regex.Pattern buyerPattern = java.util.regex.Pattern.compile("下单人:\\s*(.*?)\\s*(?=" + nextField + "|\\Z)", java.util.regex.Pattern.DOTALL);
java.util.regex.Matcher buyerMatcher = buyerPattern.matcher(input);
if (buyerMatcher.find()) {
String buyer = buyerMatcher.group(1).trim();
// 如果提取的内容包含换行符,可能是提取过度了,只取第一行
if (buyer.contains("\n")) {
buyer = buyer.split("\n")[0].trim();
}
fields.put("下单人", buyer);
}
JDOrder order = new JDOrder(); JDOrder order = new JDOrder();
order.setRemark(fields.getOrDefault("", null)); // 单号格式2025-12-13 006
String orderNo = fields.getOrDefault("", "").trim();
order.setRemark(orderNo);
// 处理分销标记:如果提取的内容包含换行符,说明可能提取过度了,只取第一行 // 处理分销标记
String distributionMark = fields.getOrDefault("分销标记", null); String distributionMark = fields.getOrDefault("分销标记", null);
if (distributionMark != null && distributionMark.contains("\n")) { if (distributionMark != null && distributionMark.contains("\n")) {
// 如果包含换行符,只取第一行,并清理可能的额外内容
String firstLine = distributionMark.split("\n")[0].trim(); String firstLine = distributionMark.split("\n")[0].trim();
// 检查第一行是否包含其他字段的关键词(如"型号:"),如果有则截断 if (firstLine.contains("型号:") || firstLine.contains("下单链接")) {
if (firstLine.contains("型号:") || firstLine.contains("链接:")) {
int index = firstLine.indexOf("型号:"); int index = firstLine.indexOf("型号:");
if (index < 0) index = firstLine.indexOf("链接"); if (index < 0) index = firstLine.indexOf("下单链接");
if (index > 0) { if (index > 0) {
firstLine = firstLine.substring(0, index).trim(); firstLine = firstLine.substring(0, index).trim();
} }
} }
distributionMark = firstLine; distributionMark = firstLine;
} }
// 如果分销标记是H-TF格式包含括号只保留H-TF
if (distributionMark != null && distributionMark.startsWith("H-TF(")) { if (distributionMark != null && distributionMark.startsWith("H-TF(")) {
distributionMark = "H-TF"; distributionMark = "H-TF";
} }
order.setDistributionMark(distributionMark); order.setDistributionMark(distributionMark);
// 优先从字段中获取第三方单号,如果没有则从分销标记中提取 // 型号
order.setModelNumber(fields.getOrDefault("型号", null));
// 下单链接(新格式)或链接(旧格式)
String link = fields.getOrDefault("下单链接(必须用这个)", null);
if (link == null) {
link = fields.getOrDefault("链接", null);
}
order.setLink(link);
// 备注字段
order.setStatus(fields.getOrDefault("备注", null));
// 第三方单号
String thirdPartyOrderNo = fields.getOrDefault("第三方单号", null); String thirdPartyOrderNo = fields.getOrDefault("第三方单号", null);
if (thirdPartyOrderNo != null) { if (thirdPartyOrderNo != null) {
// 清理换行符和空白字符
thirdPartyOrderNo = thirdPartyOrderNo.replaceAll("\\s+", "").trim(); thirdPartyOrderNo = thirdPartyOrderNo.replaceAll("\\s+", "").trim();
} }
if (thirdPartyOrderNo == null || thirdPartyOrderNo.isEmpty()) { if ((thirdPartyOrderNo == null || thirdPartyOrderNo.isEmpty()) && distributionMark != null) {
if (distributionMark != null && !distributionMark.isEmpty()) { thirdPartyOrderNo = extractOrderNumber(distributionMark);
thirdPartyOrderNo = extractOrderNumber(distributionMark); }
if (thirdPartyOrderNo != null && !thirdPartyOrderNo.trim().isEmpty()) {
order.setThirdPartyOrderNo(thirdPartyOrderNo.trim());
}
// 下单付款(新格式)或下单付款(旧格式)
String paymentStr = fields.getOrDefault("下单付款(注意核对)", null);
if (paymentStr == null) {
paymentStr = fields.getOrDefault("下单付款", "0");
}
try {
paymentStr = paymentStr.trim();
if (!paymentStr.isEmpty() && !paymentStr.equals("0")) {
order.setPaymentAmount(Double.parseDouble(paymentStr));
} }
}
// 保存第三方单号到订单对象
order.setThirdPartyOrderNo(thirdPartyOrderNo != null && !thirdPartyOrderNo.trim().isEmpty() ? thirdPartyOrderNo.trim() : null);
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) { } catch (Exception ignore) {
} }
// 后返金额(新格式)或后返金额(旧格式)
String rebateStr = fields.getOrDefault("后返金额(注意核对)", null);
if (rebateStr == null) {
rebateStr = fields.getOrDefault("后返金额", "0");
}
try { try {
order.setRebateAmount(Double.parseDouble(fields.getOrDefault("后返金额", "0"))); rebateStr = rebateStr.trim();
if (!rebateStr.isEmpty() && !rebateStr.equals("0")) {
order.setRebateAmount(Double.parseDouble(rebateStr));
}
} catch (Exception ignore) { } catch (Exception ignore) {
} }
order.setAddress(fields.getOrDefault("地址", null));
// 写入数据库时清理物流链接只保留URL // 下单地址(新格式)或地址(旧格式)
order.setLogisticsLink(extractFirstUrl(fields.getOrDefault("物流链接", ""))); String address = fields.getOrDefault("下单地址(注意带分机)", null);
order.setOrderId(fields.getOrDefault("订单号", null)); if (address == null) {
order.setBuyer(fields.getOrDefault("下单人", null)); address = fields.getOrDefault("地址", null);
// 京粉实际价格不从表单解析而是从数据库order_rows表中查询获取 }
order.setAddress(address);
// 物流链接
String logisticsLink = fields.getOrDefault("物流链接(需填)", null);
if (logisticsLink == null) {
logisticsLink = fields.getOrDefault("物流链接", "");
}
order.setLogisticsLink(extractFirstUrl(logisticsLink));
// 订单号
String orderId = fields.getOrDefault("订单号(需填)", null);
if (orderId == null) {
orderId = fields.getOrDefault("订单号", null);
}
order.setOrderId(orderId);
// 下单人
String buyer = fields.getOrDefault("下单人(需填)", null);
if (buyer == null) {
buyer = fields.getOrDefault("下单人", null);
}
order.setBuyer(buyer);
// 默认参与统计 // 默认参与统计
order.setIsCountEnabled(1); order.setIsCountEnabled(1);
// 设置下单时间
try { try {
String dateStr = fields.getOrDefault("", "").split(" ")[0]; if (!orderNo.isEmpty()) {
java.text.SimpleDateFormat sdf2 = new java.text.SimpleDateFormat("yyyy-MM-dd"); String dateStr = orderNo.split("\\s+")[0]; // 从"2025-12-13 006"中提取日期部分
order.setOrderTime(sdf2.parse(dateStr)); java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
order.setOrderTime(sdf.parse(dateStr));
} else {
order.setOrderTime(new Date());
}
} catch (Exception e) { } catch (Exception e) {
order.setOrderTime(new Date()); order.setOrderTime(new Date());
} }
return order; return order;
} }
// 提取字段的方法(支持分隔线,用于新格式)
private void extractFieldWithSeparator(String input, Map<String, String> map, String startKeyword, String endKeyword) {
try {
String escapedStart = java.util.regex.Pattern.quote(startKeyword);
String escapedEnd = java.util.regex.Pattern.quote(endKeyword);
// 匹配模式startKeyword + 可选的空白和换行 + 字段值(非贪婪,支持多行) + 后面是换行+endKeyword或换行+分隔线或结束
String patternStr = escapedStart + "[\\s\\n]*([\\s\\S]*?)(?=\\s*\\n?\\s*" + escapedEnd + "|\\s*\\n?\\s*—————————|\\Z)";
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(patternStr, java.util.regex.Pattern.DOTALL);
java.util.regex.Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
String value = matcher.group(1);
if (value != null) {
value = value.trim();
// 去掉可能的分隔线(在值的前后)
value = value.replaceAll("^—————————[\\s\\n]*", "").replaceAll("[\\s\\n]*—————————$", "").trim();
// 去掉字段标签本身(如果被匹配到了)
value = value.replaceAll("^" + escapedStart, "").trim();
// 保存字段值使用去掉冒号的key
String key = startKeyword.replace("", "").trim();
if (!value.isEmpty()) {
map.put(key, value);
}
}
}
} catch (Exception e) {
System.err.println("提取字段失败: startKeyword=" + startKeyword + ", endKeyword=" + endKeyword + ", error=" + e.getMessage());
}
}
private void extractField(String input, Map<String, String> map, String startKeyword, String endKeyword) { private void extractField(String input, Map<String, String> map, String startKeyword, String endKeyword) {
// 如果结束关键词为空,匹配到字符串末尾 // 如果结束关键词为空,匹配到字符串末尾
String endPattern = endKeyword.isEmpty() ? "\\Z" : endKeyword; String endPattern = endKeyword.isEmpty() ? "\\Z" : endKeyword;