1
This commit is contained in:
@@ -1056,66 +1056,61 @@ public class TencentDocController extends BaseController {
|
||||
return AjaxResult.error("无法识别表头,表头数据为空");
|
||||
}
|
||||
|
||||
// 查找所有相关列
|
||||
log.info("开始识别表头列,共 {} 列", headerRowData.size());
|
||||
// 列名须与表格完全一致(仅忽略首尾空白、不间断空格等):备注、是否安排、物流单号、下单电话、标记、京东下单订单号;另需「单号」或「第三方单号」
|
||||
log.info("开始识别表头列(完全匹配列名),共 {} 列", headerRowData.size());
|
||||
for (int i = 0; i < headerRowData.size(); i++) {
|
||||
String cellValue = headerRowData.getString(i);
|
||||
if (cellValue != null) {
|
||||
String cellValueTrim = cellValue.trim();
|
||||
log.debug("列 {} 内容: [{}]", i, cellValueTrim);
|
||||
if (cellValue == null) {
|
||||
continue;
|
||||
}
|
||||
String norm = TencentDocDataParser.normalizeTencentDocHeader(cellValue);
|
||||
log.debug("列 {} 原始: [{}] 规范化: [{}]", i, cellValue.trim(), norm);
|
||||
|
||||
if (jdPlaceOrderNoColumn == null && TencentDocDataParser.isJdPlaceOrderNoHeader(cellValueTrim)) {
|
||||
jdPlaceOrderNoColumn = i;
|
||||
log.info("✓ 识别到 '京东下单订单号' 列:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
|
||||
// 识别"单号"列
|
||||
if (orderNoColumn == null && cellValueTrim.contains("单号")
|
||||
&& !TencentDocDataParser.isJdPlaceOrderNoHeader(cellValueTrim)
|
||||
&& !cellValueTrim.contains("物流")) {
|
||||
orderNoColumn = i;
|
||||
log.info("✓ 识别到 '单号' 列:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
|
||||
// 识别"物流单号"或"物流链接"列
|
||||
if (logisticsLinkColumn == null && (cellValueTrim.contains("物流单号") || cellValueTrim.contains("物流链接"))) {
|
||||
logisticsLinkColumn = i;
|
||||
log.info("✓ 识别到 '物流单号' 列:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
|
||||
// 识别"备注"列(可选)
|
||||
if (remarkColumn == null && cellValueTrim.contains("备注")) {
|
||||
remarkColumn = i;
|
||||
log.info("✓ 识别到 '备注' 列:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
|
||||
// 识别"是否安排"列(可选)
|
||||
if (arrangedColumn == null && (cellValueTrim.contains("是否安排") || cellValueTrim.contains("安排"))) {
|
||||
arrangedColumn = i;
|
||||
log.info("✓ 识别到 '是否安排' 列:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
|
||||
// 识别"标记"列(可选)
|
||||
if (markColumn == null && cellValueTrim.contains("标记")) {
|
||||
markColumn = i;
|
||||
log.info("✓ 识别到 '标记' 列:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
|
||||
// 识别"下单电话"列(可选)
|
||||
if (phoneColumn == null && (cellValueTrim.contains("下单电话"))) {
|
||||
phoneColumn = i;
|
||||
log.info("✓ 识别到 '下单电话' 列:第 {} 列(索引{}),列名: [{}]", i + 1, i, cellValueTrim);
|
||||
}
|
||||
if (jdPlaceOrderNoColumn == null && TencentDocDataParser.headerEquals(cellValue, "京东下单订单号")) {
|
||||
jdPlaceOrderNoColumn = i;
|
||||
log.info("✓ 列名完全匹配「京东下单订单号」:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (orderNoColumn == null && TencentDocDataParser.headerEquals(cellValue, "单号")) {
|
||||
orderNoColumn = i;
|
||||
log.info("✓ 列名完全匹配「单号」:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (orderNoColumn == null && TencentDocDataParser.headerEquals(cellValue, "第三方单号")) {
|
||||
orderNoColumn = i;
|
||||
log.info("✓ 列名完全匹配「第三方单号」:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (logisticsLinkColumn == null && TencentDocDataParser.headerEquals(cellValue, "物流单号")) {
|
||||
logisticsLinkColumn = i;
|
||||
log.info("✓ 列名完全匹配「物流单号」:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (logisticsLinkColumn == null && TencentDocDataParser.headerEquals(cellValue, "物流链接")) {
|
||||
logisticsLinkColumn = i;
|
||||
log.warn("✓ 列名匹配「物流链接」(建议改为「物流单号」):第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (remarkColumn == null && TencentDocDataParser.headerEquals(cellValue, "备注")) {
|
||||
remarkColumn = i;
|
||||
log.info("✓ 列名完全匹配「备注」:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (arrangedColumn == null && TencentDocDataParser.headerEquals(cellValue, "是否安排")) {
|
||||
arrangedColumn = i;
|
||||
log.info("✓ 列名完全匹配「是否安排」:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (markColumn == null && TencentDocDataParser.headerEquals(cellValue, "标记")) {
|
||||
markColumn = i;
|
||||
log.info("✓ 列名完全匹配「标记」:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (phoneColumn == null && TencentDocDataParser.headerEquals(cellValue, "下单电话")) {
|
||||
phoneColumn = i;
|
||||
log.info("✓ 列名完全匹配「下单电话」:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
}
|
||||
log.info("表头列识别完成");
|
||||
|
||||
// 检查必需的列是否都已识别
|
||||
if (orderNoColumn == null) {
|
||||
return AjaxResult.error("无法找到'单号'列,请检查表头是否包含'单号'字段");
|
||||
return AjaxResult.error("无法找到列名完全为「单号」或「第三方单号」的列(请与表格列名一致,勿加空格或后缀)");
|
||||
}
|
||||
if (logisticsLinkColumn == null) {
|
||||
return AjaxResult.error("无法找到'物流单号'或'物流链接'列,请检查表头");
|
||||
return AjaxResult.error("无法找到列名完全为「物流单号」的列(兼容「物流链接」);请与表格列名一致");
|
||||
}
|
||||
|
||||
// 提示可选列的识别情况
|
||||
@@ -2237,24 +2232,29 @@ public class TencentDocController extends BaseController {
|
||||
|
||||
for (int i = 0; i < headerRowData.size(); i++) {
|
||||
String cellValue = headerRowData.getString(i);
|
||||
if (cellValue != null) {
|
||||
String cellValueTrim = cellValue.trim();
|
||||
|
||||
if (orderNoColumn == null && cellValueTrim.contains("单号") && !cellValueTrim.contains("物流")
|
||||
&& !TencentDocDataParser.isJdPlaceOrderNoHeader(cellValueTrim)) {
|
||||
orderNoColumn = i;
|
||||
log.info("✓ 识别到 '单号' 列:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
|
||||
if (logisticsLinkColumn == null && (cellValueTrim.contains("物流单号") || cellValueTrim.contains("物流链接"))) {
|
||||
logisticsLinkColumn = i;
|
||||
log.info("✓ 识别到 '物流单号' 列:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (cellValue == null) {
|
||||
continue;
|
||||
}
|
||||
if (orderNoColumn == null && TencentDocDataParser.headerEquals(cellValue, "单号")) {
|
||||
orderNoColumn = i;
|
||||
log.info("✓ 列名完全匹配「单号」:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (orderNoColumn == null && TencentDocDataParser.headerEquals(cellValue, "第三方单号")) {
|
||||
orderNoColumn = i;
|
||||
log.info("✓ 列名完全匹配「第三方单号」:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (logisticsLinkColumn == null && TencentDocDataParser.headerEquals(cellValue, "物流单号")) {
|
||||
logisticsLinkColumn = i;
|
||||
log.info("✓ 列名完全匹配「物流单号」:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (logisticsLinkColumn == null && TencentDocDataParser.headerEquals(cellValue, "物流链接")) {
|
||||
logisticsLinkColumn = i;
|
||||
log.info("✓ 列名匹配「物流链接」:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (orderNoColumn == null || logisticsLinkColumn == null) {
|
||||
return AjaxResult.error("无法识别表头列,请确保表头包含'单号'和'物流单号'列");
|
||||
return AjaxResult.error("无法识别表头列,请确保存在列名完全为「单号」或「第三方单号」,以及「物流单号」(或「物流链接」)");
|
||||
}
|
||||
|
||||
// 统计结果
|
||||
@@ -2536,24 +2536,29 @@ public class TencentDocController extends BaseController {
|
||||
|
||||
for (int i = 0; i < headerRowData.size(); i++) {
|
||||
String cellValue = headerRowData.getString(i);
|
||||
if (cellValue != null) {
|
||||
String cellValueTrim = cellValue.trim();
|
||||
|
||||
if (orderNoColumn == null && cellValueTrim.contains("单号") && !cellValueTrim.contains("物流")
|
||||
&& !TencentDocDataParser.isJdPlaceOrderNoHeader(cellValueTrim)) {
|
||||
orderNoColumn = i;
|
||||
log.info("✓ 识别到 '单号' 列:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
|
||||
if (logisticsLinkColumn == null && (cellValueTrim.contains("物流单号") || cellValueTrim.contains("物流链接"))) {
|
||||
logisticsLinkColumn = i;
|
||||
log.info("✓ 识别到 '物流单号' 列:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (cellValue == null) {
|
||||
continue;
|
||||
}
|
||||
if (orderNoColumn == null && TencentDocDataParser.headerEquals(cellValue, "单号")) {
|
||||
orderNoColumn = i;
|
||||
log.info("✓ 列名完全匹配「单号」:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (orderNoColumn == null && TencentDocDataParser.headerEquals(cellValue, "第三方单号")) {
|
||||
orderNoColumn = i;
|
||||
log.info("✓ 列名完全匹配「第三方单号」:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (logisticsLinkColumn == null && TencentDocDataParser.headerEquals(cellValue, "物流单号")) {
|
||||
logisticsLinkColumn = i;
|
||||
log.info("✓ 列名完全匹配「物流单号」:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
if (logisticsLinkColumn == null && TencentDocDataParser.headerEquals(cellValue, "物流链接")) {
|
||||
logisticsLinkColumn = i;
|
||||
log.info("✓ 列名匹配「物流链接」:第 {} 列(索引{})", i + 1, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (orderNoColumn == null || logisticsLinkColumn == null) {
|
||||
return AjaxResult.error("无法识别表头列,请确保表头包含'单号'和'物流单号'列");
|
||||
return AjaxResult.error("无法识别表头列,请确保存在列名完全为「单号」或「第三方单号」,以及「物流单号」(或「物流链接」)");
|
||||
}
|
||||
|
||||
// 统计结果
|
||||
|
||||
@@ -15,6 +15,8 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
/**
|
||||
* 小红书/抖音内容生成Service业务层处理
|
||||
@@ -41,7 +43,10 @@ public class SocialMediaServiceImpl implements ISocialMediaService
|
||||
"keywords",
|
||||
"content:xhs",
|
||||
"content:douyin",
|
||||
"content:both"
|
||||
"content:both",
|
||||
"xianyu:wenan_base",
|
||||
"xianyu:jiaonixiadan_extra",
|
||||
"xianyu:title_clean_regex"
|
||||
};
|
||||
|
||||
// 模板说明
|
||||
@@ -50,6 +55,9 @@ public class SocialMediaServiceImpl implements ISocialMediaService
|
||||
put("content:xhs", "小红书文案生成提示词模板\n占位符:%s - 商品名称,%s - 价格信息,%s - 关键词信息");
|
||||
put("content:douyin", "抖音文案生成提示词模板\n占位符:%s - 商品名称,%s - 价格信息,%s - 关键词信息");
|
||||
put("content:both", "通用文案生成提示词模板\n占位符:%s - 商品名称,%s - 价格信息,%s - 关键词信息");
|
||||
put("xianyu:wenan_base", "闲鱼文案·正文基础说明\n用于「一键代下」与「教你下单」两版文案中,紧接在标题/型号行之后(纯文本,无占位符)");
|
||||
put("xianyu:jiaonixiadan_extra", "闲鱼文案·教你下单版尾部附加说明\n接在「更新日期:yyyy-MM-dd」之后(纯文本)");
|
||||
put("xianyu:title_clean_regex", "闲鱼文案·标题/型号清洗正则\n从标题与型号备注中移除营销敏感片段;须为 Java 正则,匹配到的内容会被删除");
|
||||
}};
|
||||
|
||||
/** 与 Jarvis_java SocialMediaLlmClient 使用相同 Redis 键 */
|
||||
@@ -61,19 +69,19 @@ public class SocialMediaServiceImpl implements ISocialMediaService
|
||||
private static final String LLM_MODE_OLLAMA = "ollama";
|
||||
private static final String LLM_MODE_OPENAI = "openai";
|
||||
|
||||
/** 闲鱼文案-通用基础说明 */
|
||||
private static final String WENAN_BASE =
|
||||
/** 闲鱼文案-通用基础说明(Redis 未配置时使用) */
|
||||
private static final String DEFAULT_XIANYU_WENAN_BASE =
|
||||
"全新未拆封正品,包邮包安装,支持查验后再签收。\n"
|
||||
+ "运损可免费换新。\n"
|
||||
+ "售后全部支持全国联保。";
|
||||
/** 闲鱼文案-教你下单附加说明(不含更新日期) */
|
||||
private static final String WENAN_JIAONIXIADAN_EXTRA =
|
||||
private static final String DEFAULT_XIANYU_JIAONIXIADAN_EXTRA =
|
||||
"\n无偿提供下单方案,包价格成立:\n"
|
||||
+ "只要告诉我【需要下单的型号 + 收货地址】,\n"
|
||||
+ "我会根据你所在地区和需求,\n"
|
||||
+ "优先回复你合适的下单渠道和详细步骤,让你安全省钱地完成下单。";
|
||||
/** 标题/型号清洗:去掉营销敏感词 */
|
||||
private static final String TITLE_CLEAN_REGEX = "以旧|政府|换新|领取|国家|补贴|15%|20%|国补|立减|【|】";
|
||||
private static final String DEFAULT_XIANYU_TITLE_CLEAN_REGEX = "以旧|政府|换新|领取|国家|补贴|15%|20%|国补|立减|【|】";
|
||||
|
||||
/**
|
||||
* 提取商品标题关键词
|
||||
@@ -352,6 +360,13 @@ public class SocialMediaServiceImpl implements ISocialMediaService
|
||||
if (StringUtils.isEmpty(templateValue)) {
|
||||
return AjaxResult.error("模板内容不能为空");
|
||||
}
|
||||
if ("xianyu:title_clean_regex".equals(key)) {
|
||||
try {
|
||||
Pattern.compile(templateValue);
|
||||
} catch (PatternSyntaxException e) {
|
||||
return AjaxResult.error("正则表达式无效: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
redisTemplate.opsForValue().set(redisKey, templateValue);
|
||||
|
||||
log.info("保存提示词模板成功: {}", key);
|
||||
@@ -407,6 +422,12 @@ public class SocialMediaServiceImpl implements ISocialMediaService
|
||||
}
|
||||
}
|
||||
|
||||
/** Redis 无配置时返回 defaultTemplate */
|
||||
private String getPromptTemplateWithDefault(String templateKey, String defaultTemplate) {
|
||||
String fromRedis = getTemplateFromRedis(templateKey);
|
||||
return StringUtils.isNotEmpty(fromRedis) ? fromRedis : defaultTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证模板键名是否有效
|
||||
*/
|
||||
@@ -571,6 +592,9 @@ public class SocialMediaServiceImpl implements ISocialMediaService
|
||||
String cleanTitle = cleanTitleOrRemark(title.trim());
|
||||
String cleanRemark = StringUtils.isNotEmpty(remark) ? cleanTitleOrRemark(remark.trim()) : "";
|
||||
|
||||
String wenanBase = getPromptTemplateWithDefault("xianyu:wenan_base", DEFAULT_XIANYU_WENAN_BASE);
|
||||
String jiaonixiadanExtra = getPromptTemplateWithDefault("xianyu:jiaonixiadan_extra", DEFAULT_XIANYU_JIAONIXIADAN_EXTRA);
|
||||
|
||||
// 标题行
|
||||
StringBuilder daixiadanBuilder = new StringBuilder();
|
||||
daixiadanBuilder.append("(一键代下) ").append(cleanTitle).append("\n");
|
||||
@@ -578,7 +602,7 @@ public class SocialMediaServiceImpl implements ISocialMediaService
|
||||
if (StringUtils.isNotEmpty(cleanRemark)) {
|
||||
daixiadanBuilder.append("型号:").append(cleanRemark).append("\n");
|
||||
}
|
||||
daixiadanBuilder.append(WENAN_BASE);
|
||||
daixiadanBuilder.append(wenanBase);
|
||||
|
||||
// 教你下单版
|
||||
StringBuilder jiaonixiadanBuilder = new StringBuilder();
|
||||
@@ -586,11 +610,11 @@ public class SocialMediaServiceImpl implements ISocialMediaService
|
||||
if (StringUtils.isNotEmpty(cleanRemark)) {
|
||||
jiaonixiadanBuilder.append("型号:").append(cleanRemark).append("\n");
|
||||
}
|
||||
jiaonixiadanBuilder.append(WENAN_BASE).append("\n\n");
|
||||
jiaonixiadanBuilder.append(wenanBase).append("\n\n");
|
||||
|
||||
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
|
||||
String dateStr = sdf.format(new java.util.Date());
|
||||
jiaonixiadanBuilder.append("更新日期:").append(dateStr).append(WENAN_JIAONIXIADAN_EXTRA);
|
||||
jiaonixiadanBuilder.append("更新日期:").append(dateStr).append(jiaonixiadanExtra);
|
||||
|
||||
result.put("success", true);
|
||||
result.put("daixiadan", daixiadanBuilder.toString());
|
||||
@@ -599,13 +623,19 @@ public class SocialMediaServiceImpl implements ISocialMediaService
|
||||
}
|
||||
|
||||
/**
|
||||
* 清洗标题/型号中的敏感词
|
||||
* 清洗标题/型号中的敏感词(正则来自可配置模板 xianyu:title_clean_regex)
|
||||
*/
|
||||
private static String cleanTitleOrRemark(String text) {
|
||||
private String cleanTitleOrRemark(String text) {
|
||||
if (text == null) {
|
||||
return "";
|
||||
}
|
||||
return text.replaceAll(TITLE_CLEAN_REGEX, "");
|
||||
String regex = getPromptTemplateWithDefault("xianyu:title_clean_regex", DEFAULT_XIANYU_TITLE_CLEAN_REGEX);
|
||||
try {
|
||||
return text.replaceAll(regex, "");
|
||||
} catch (Exception e) {
|
||||
log.warn("标题清洗正则执行失败,使用内置默认: {}", e.getMessage());
|
||||
return text.replaceAll(DEFAULT_XIANYU_TITLE_CLEAN_REGEX, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -218,24 +218,39 @@ public class TencentDocServiceImpl implements ITencentDocService {
|
||||
|
||||
for (int i = 0; i < headerCells.size(); i++) {
|
||||
String cellText = headerCells.getString(i);
|
||||
if (cellText != null) {
|
||||
if (TencentDocDataParser.isJdPlaceOrderNoHeader(cellText)) {
|
||||
if (jdPlaceOrderNoColumn == null) {
|
||||
jdPlaceOrderNoColumn = i;
|
||||
}
|
||||
} else if (cellText.contains("日期")) dateColumn = i;
|
||||
else if (cellText.contains("公司")) companyColumn = i;
|
||||
else if (cellText.contains("单号") && !cellText.contains("物流")
|
||||
&& !TencentDocDataParser.isJdPlaceOrderNoHeader(cellText)) orderNoColumn = i;
|
||||
else if (cellText.contains("型号")) modelColumn = i;
|
||||
else if (cellText.contains("数量")) quantityColumn = i;
|
||||
else if (cellText.contains("姓名")) nameColumn = i;
|
||||
else if (cellText.contains("电话")) phoneColumn = i;
|
||||
else if (cellText.contains("地址")) addressColumn = i;
|
||||
else if (cellText.contains("价格")) priceColumn = i;
|
||||
else if (cellText.contains("备注")) remarkColumn = i;
|
||||
else if (cellText.contains("是否安排") || cellText.contains("安排")) arrangedColumn = i;
|
||||
else if (cellText.contains("物流")) logisticsColumn = i;
|
||||
if (cellText == null) {
|
||||
continue;
|
||||
}
|
||||
if (jdPlaceOrderNoColumn == null && TencentDocDataParser.isJdPlaceOrderNoHeader(cellText)) {
|
||||
jdPlaceOrderNoColumn = i;
|
||||
} else if (cellText.contains("日期")) {
|
||||
dateColumn = i;
|
||||
} else if (cellText.contains("公司")) {
|
||||
companyColumn = i;
|
||||
} else if (TencentDocDataParser.headerEquals(cellText, "单号")) {
|
||||
orderNoColumn = i;
|
||||
} else if (orderNoColumn == null && TencentDocDataParser.headerEquals(cellText, "第三方单号")) {
|
||||
orderNoColumn = i;
|
||||
} else if (cellText.contains("型号")) {
|
||||
modelColumn = i;
|
||||
} else if (cellText.contains("数量")) {
|
||||
quantityColumn = i;
|
||||
} else if (cellText.contains("姓名")) {
|
||||
nameColumn = i;
|
||||
} else if (cellText.contains("电话")) {
|
||||
phoneColumn = i;
|
||||
} else if (cellText.contains("地址")) {
|
||||
addressColumn = i;
|
||||
} else if (cellText.contains("价格")) {
|
||||
priceColumn = i;
|
||||
} else if (TencentDocDataParser.headerEquals(cellText, "备注")) {
|
||||
remarkColumn = i;
|
||||
} else if (TencentDocDataParser.headerEquals(cellText, "是否安排")) {
|
||||
arrangedColumn = i;
|
||||
} else if (TencentDocDataParser.headerEquals(cellText, "物流单号")) {
|
||||
logisticsColumn = i;
|
||||
} else if (logisticsColumn == null && TencentDocDataParser.headerEquals(cellText, "物流链接")) {
|
||||
logisticsColumn = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -215,20 +215,36 @@ public class TencentDocDataParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* 表头是否为「京东下单订单号」列(与第三方「单号」等列区分)
|
||||
* 表头规范化:去 BOM、首尾空白、不间断空格与全角空格后,去掉中间空白再比较(与腾讯表格展示列名一致)
|
||||
*/
|
||||
public static String normalizeTencentDocHeader(String raw) {
|
||||
if (raw == null) {
|
||||
return "";
|
||||
}
|
||||
String t = raw.trim();
|
||||
if (t.startsWith("\uFEFF")) {
|
||||
t = t.substring(1).trim();
|
||||
}
|
||||
t = t.replace('\u00A0', ' ').replace('\u3000', ' ');
|
||||
t = t.replaceAll("\\s+", "");
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* 表头是否与期望列名完全一致(规范化后)
|
||||
*/
|
||||
public static boolean headerEquals(String raw, String expectedName) {
|
||||
if (expectedName == null) {
|
||||
return false;
|
||||
}
|
||||
return expectedName.equals(normalizeTencentDocHeader(raw));
|
||||
}
|
||||
|
||||
/**
|
||||
* 表头是否为「京东下单订单号」列(列名须完全一致)
|
||||
*/
|
||||
public static boolean isJdPlaceOrderNoHeader(String cellValueTrim) {
|
||||
if (cellValueTrim == null) {
|
||||
return false;
|
||||
}
|
||||
String t = cellValueTrim.trim();
|
||||
if (t.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
if (t.contains("京东下单订单号")) {
|
||||
return true;
|
||||
}
|
||||
return t.contains("京东") && t.contains("下单") && t.contains("订单号");
|
||||
return headerEquals(cellValueTrim, "京东下单订单号");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user