This commit is contained in:
Leo
2025-11-10 23:32:04 +08:00
parent af68b529b0
commit e2facc3099

View File

@@ -37,6 +37,15 @@ public class JDOrderController extends BaseController {
private final IJDOrderService jdOrderService;
private final IOrderRowsService orderRowsService;
private final IGiftCouponService giftCouponService;
private static final java.util.regex.Pattern URL_DETECT_PATTERN = java.util.regex.Pattern.compile(
"(https?://[^\\s]+)|(u\\.jd\\.com/[^\\s]+)",
java.util.regex.Pattern.CASE_INSENSITIVE);
private static final java.util.regex.Pattern UJD_LINK_PATTERN = java.util.regex.Pattern.compile(
"^https?://u\\.jd\\.com/[A-Za-z0-9]+[A-Za-z0-9_-]*$",
java.util.regex.Pattern.CASE_INSENSITIVE);
private static final java.util.regex.Pattern JINGFEN_LINK_PATTERN = java.util.regex.Pattern.compile(
"^https?://jingfen\\.jd\\.com/detail/[A-Za-z0-9]+\\.html$",
java.util.regex.Pattern.CASE_INSENSITIVE);
public JDOrderController(IJDOrderService jdOrderService, IOrderRowsService orderRowsService, IGiftCouponService giftCouponService) {
this.jdOrderService = jdOrderService;
@@ -566,22 +575,20 @@ public class JDOrderController extends BaseController {
content.length(), amount, quantity, owner);
// 提取文本中的所有URL京东链接
java.util.List<String> urls = new java.util.ArrayList<>();
java.util.regex.Pattern urlPattern = java.util.regex.Pattern.compile(
"(https?://[^\\s]+)|(u\\.jd\\.com/[^\\s]+)",
java.util.regex.Pattern.CASE_INSENSITIVE);
java.util.regex.Matcher matcher = urlPattern.matcher(content);
java.util.List<UrlSegment> urlSegments = new java.util.ArrayList<>();
java.util.regex.Matcher matcher = URL_DETECT_PATTERN.matcher(content);
while (matcher.find()) {
String url = matcher.group(0);
if (url != null && !url.trim().isEmpty()) {
urls.add(url.trim());
String segment = matcher.group(0);
UrlSegment urlInfo = parseUrlSegment(segment);
if (urlInfo != null) {
urlSegments.add(urlInfo);
}
}
logger.info("文本URL替换 - 提取到{}个URL", urls.size());
logger.info("文本URL替换 - 提取到{}个URL", urlSegments.size());
if (urls.isEmpty()) {
if (urlSegments.isEmpty()) {
return AjaxResult.success(new JSONObject()
.fluentPut("replacedContent", content)
.fluentPut("originalContent", content)
@@ -596,17 +603,29 @@ public class JDOrderController extends BaseController {
JSONArray replacementInfo = new JSONArray();
int successCount = 0;
for (int i = 0; i < urls.size(); i++) {
String originalUrl = urls.get(i);
logger.info("处理第{}/{}个URL: {}", i + 1, urls.size(), originalUrl);
for (int i = 0; i < urlSegments.size(); i++) {
UrlSegment urlSegment = urlSegments.get(i);
logger.info("处理第{}/{}个URL: {}", i + 1, urlSegments.size(), urlSegment.urlPart);
JSONObject product = null; // 在try外部声明以便在catch中使用
try {
if (urlSegment.normalizedJdUrl == null) {
logger.warn("URL{}不是京东推广链接,跳过: {}", i + 1, urlSegment.original);
JSONObject info = new JSONObject();
info.put("index", i + 1);
info.put("originalUrl", urlSegment.urlPart);
info.put("newUrl", urlSegment.urlPart);
info.put("success", false);
info.put("error", "非京东推广链接或格式不支持");
replacementInfo.add(info);
continue;
}
// 1. 查询该URL的商品信息
String queryUrl = requestUrl + "generatePromotionContent";
JSONObject queryParam = new JSONObject();
queryParam.put("skey", skey);
queryParam.put("promotionContent", originalUrl);
queryParam.put("promotionContent", urlSegment.normalizedJdUrl);
String queryResult = HttpUtils.sendJsonPost(queryUrl, queryParam.toJSONString());
logger.debug("商品查询响应: {}", queryResult);
@@ -643,11 +662,11 @@ public class JDOrderController extends BaseController {
errorMsg = apiError;
}
}
logger.warn("URL{}商品信息查询失败: {}", originalUrl, errorMsg);
logger.warn("URL{}商品信息查询失败: {}", urlSegment.urlPart, errorMsg);
JSONObject info = new JSONObject();
info.put("index", i + 1);
info.put("originalUrl", originalUrl);
info.put("newUrl", originalUrl);
info.put("originalUrl", urlSegment.urlPart);
info.put("newUrl", urlSegment.urlPart);
info.put("success", false);
info.put("error", errorMsg);
replacementInfo.add(info);
@@ -704,8 +723,8 @@ public class JDOrderController extends BaseController {
logger.warn("POP商品{}缺少有效的oriItemId/materialUrl/skuId", product.getString("skuName"));
JSONObject info = new JSONObject();
info.put("index", i + 1);
info.put("originalUrl", originalUrl);
info.put("newUrl", originalUrl);
info.put("originalUrl", urlSegment.urlPart);
info.put("newUrl", urlSegment.urlPart);
info.put("success", false);
info.put("error", "POP商品信息不完整");
replacementInfo.add(info);
@@ -723,8 +742,8 @@ public class JDOrderController extends BaseController {
logger.warn("自营商品{}缺少有效的skuId/materialUrl", product.getString("skuName"));
JSONObject info = new JSONObject();
info.put("index", i + 1);
info.put("originalUrl", originalUrl);
info.put("newUrl", originalUrl);
info.put("originalUrl", urlSegment.urlPart);
info.put("newUrl", urlSegment.urlPart);
info.put("success", false);
info.put("error", "自营商品信息不完整");
replacementInfo.add(info);
@@ -749,11 +768,11 @@ public class JDOrderController extends BaseController {
errorMsg = apiError;
}
}
logger.warn("URL{}礼金创建失败: {}", originalUrl, errorMsg);
logger.warn("URL{}礼金创建失败: {}", urlSegment.urlPart, errorMsg);
JSONObject info = new JSONObject();
info.put("index", i + 1);
info.put("originalUrl", originalUrl);
info.put("newUrl", originalUrl);
info.put("originalUrl", urlSegment.urlPart);
info.put("newUrl", urlSegment.urlPart);
info.put("success", false);
info.put("error", errorMsg);
if (product != null && product.getString("skuName") != null) {
@@ -769,7 +788,7 @@ public class JDOrderController extends BaseController {
String transferUrl = requestUrl + "transfer";
JSONObject transferParam = new JSONObject();
transferParam.put("skey", skey);
transferParam.put("materialUrl", originalUrl);
transferParam.put("materialUrl", urlSegment.normalizedJdUrl);
transferParam.put("giftCouponKey", giftCouponKey);
String transferResult = HttpUtils.sendJsonPost(transferUrl, transferParam.toJSONString());
@@ -789,11 +808,11 @@ public class JDOrderController extends BaseController {
errorMsg = apiError;
}
}
logger.warn("URL{}转链失败: {}", originalUrl, errorMsg);
logger.warn("URL{}转链失败: {}", urlSegment.urlPart, errorMsg);
JSONObject info = new JSONObject();
info.put("index", i + 1);
info.put("originalUrl", originalUrl);
info.put("newUrl", originalUrl);
info.put("originalUrl", urlSegment.urlPart);
info.put("newUrl", urlSegment.urlPart);
info.put("success", false);
info.put("giftCouponKey", giftCouponKey);
info.put("error", errorMsg);
@@ -807,11 +826,11 @@ public class JDOrderController extends BaseController {
String shortURL = transferData.getString("shortURL");
// 4. 替换文本中的URL
replacedContent = replacedContent.replace(originalUrl, shortURL);
replacedContent = replaceUrlInContent(replacedContent, urlSegment, shortURL);
JSONObject info = new JSONObject();
info.put("index", i + 1);
info.put("originalUrl", originalUrl);
info.put("originalUrl", urlSegment.urlPart);
info.put("newUrl", shortURL);
info.put("success", true);
info.put("giftCouponKey", giftCouponKey);
@@ -819,18 +838,18 @@ public class JDOrderController extends BaseController {
replacementInfo.add(info);
successCount++;
logger.info("URL{}处理成功: {} -> {}", i + 1, originalUrl, shortURL);
logger.info("URL{}处理成功: {} -> {}", i + 1, urlSegment.urlPart, shortURL);
} catch (Exception e) {
logger.error("处理URL{}失败: {}", originalUrl, e.getMessage(), e);
logger.error("处理URL{}失败: {}", urlSegment.urlPart, e.getMessage(), e);
String errorMsg = e.getMessage();
if (errorMsg == null || errorMsg.trim().isEmpty()) {
errorMsg = "处理失败: " + e.getClass().getSimpleName();
}
JSONObject info = new JSONObject();
info.put("index", i + 1);
info.put("originalUrl", originalUrl);
info.put("newUrl", originalUrl);
info.put("originalUrl", urlSegment.urlPart);
info.put("newUrl", urlSegment.urlPart);
info.put("success", false);
info.put("error", errorMsg);
if (product != null && product.getString("skuName") != null) {
@@ -840,13 +859,13 @@ public class JDOrderController extends BaseController {
}
}
logger.info("文本URL替换完成 - 成功{}/{}", successCount, urls.size());
logger.info("文本URL替换完成 - 成功{}/{}", successCount, urlSegments.size());
JSONObject response = new JSONObject();
response.put("replacedContent", replacedContent);
response.put("originalContent", content);
response.put("replacements", replacementInfo);
response.put("totalUrls", urls.size());
response.put("totalUrls", urlSegments.size());
response.put("replacedCount", successCount);
return AjaxResult.success(response);
@@ -1110,4 +1129,80 @@ public class JDOrderController extends BaseController {
}
return result.toString();
}
private static class UrlSegment {
private final String original;
private final String urlPart;
private final String suffix;
private final String normalizedJdUrl;
private UrlSegment(String original, String urlPart, String suffix, String normalizedJdUrl) {
this.original = original;
this.urlPart = urlPart;
this.suffix = suffix;
this.normalizedJdUrl = normalizedJdUrl;
}
}
private static UrlSegment parseUrlSegment(String segment) {
if (segment == null || segment.trim().isEmpty()) {
return null;
}
String original = segment.trim();
int urlLength = calculateUrlLength(original);
if (urlLength <= 0) {
return null;
}
String urlPart = original.substring(0, urlLength);
String suffix = original.substring(urlLength);
String normalized = normalizeJdUrl(urlPart);
return new UrlSegment(original, urlPart, suffix, normalized);
}
private static int calculateUrlLength(String text) {
int length = 0;
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (isAllowedUrlChar(c)) {
length++;
} else {
break;
}
}
return length;
}
private static boolean isAllowedUrlChar(char c) {
if (c <= 0x7F) {
return Character.isLetterOrDigit(c) || "-._~:/?#[]@!$&'()*+,;=%".indexOf(c) >= 0;
}
return false;
}
private static String normalizeJdUrl(String urlPart) {
if (urlPart == null || urlPart.isEmpty()) {
return null;
}
String normalized = urlPart;
if (!normalized.startsWith("http://") && !normalized.startsWith("https://")) {
normalized = "https://" + normalized;
}
if (UJD_LINK_PATTERN.matcher(normalized).matches() || JINGFEN_LINK_PATTERN.matcher(normalized).matches()) {
return normalized;
}
return null;
}
private static String replaceUrlInContent(String content, UrlSegment segment, String newUrl) {
if (content == null || segment == null || newUrl == null || newUrl.trim().isEmpty()) {
return content;
}
String suffix = segment.suffix != null ? segment.suffix : "";
String replacementWithSuffix = newUrl + suffix;
String result = content.replace(segment.original, replacementWithSuffix);
if (result.equals(content) && !segment.original.equals(segment.urlPart)) {
result = result.replace(segment.urlPart, newUrl);
}
return result;
}
}