1
This commit is contained in:
@@ -12,6 +12,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.MessageDigest;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
@@ -1147,24 +1149,6 @@ public class InstructionServiceImpl implements IInstructionService {
|
|||||||
stringRedisTemplate.opsForValue().set(orderNumberKey, orderNumberForDedup, 1, TimeUnit.DAYS);
|
stringRedisTemplate.opsForValue().set(orderNumberKey, orderNumberForDedup, 1, TimeUnit.DAYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 第二重判断:地址 24 小时去重校验(白名单放行)
|
|
||||||
if (stringRedisTemplate != null) {
|
|
||||||
String addressKey = "address:" + address;
|
|
||||||
String existed = stringRedisTemplate.opsForValue().get(addressKey);
|
|
||||||
if (existed != null) {
|
|
||||||
if (!(existed.contains("李波") || existed.contains("吴胜硕") || existed.contains("小硕硕"))) {
|
|
||||||
// 如果强制生成,跳过地址重复检查
|
|
||||||
if (!forceGenerate) {
|
|
||||||
// 返回特殊错误码,前端会识别并弹出验证码
|
|
||||||
return "ERROR_CODE:ADDRESS_DUPLICATE\n此地址已经存在,请勿重复生成订单";
|
|
||||||
}
|
|
||||||
// forceGenerate为true时,跳过地址重复检查,继续执行
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 只有在不强制生成或地址不存在时才设置Redis(强制生成时也更新Redis记录)
|
|
||||||
stringRedisTemplate.opsForValue().set(addressKey, address, 1, TimeUnit.DAYS);
|
|
||||||
}
|
|
||||||
|
|
||||||
String today = new java.text.SimpleDateFormat("yyyy-MM-dd ").format(new Date());
|
String today = new java.text.SimpleDateFormat("yyyy-MM-dd ").format(new Date());
|
||||||
String todayNoSpace = today.trim();
|
String todayNoSpace = today.trim();
|
||||||
String keyWithSpace = "order_count:" + today; // 带空格
|
String keyWithSpace = "order_count:" + today; // 带空格
|
||||||
@@ -1188,14 +1172,40 @@ public class InstructionServiceImpl implements IInstructionService {
|
|||||||
StringBuilder out = new StringBuilder();
|
StringBuilder out = new StringBuilder();
|
||||||
int total = Math.max(1, num);
|
int total = Math.max(1, num);
|
||||||
|
|
||||||
|
// 第二重:同日 + 型号 + 地址 槽位。重复提交视为「更新」——复用当日已分配序号,不递增全局 order_count;强制生成则始终新占号并覆盖槽位。
|
||||||
|
String slotDigest = digestShengSlot(model, address);
|
||||||
|
String slotKey = "sheng_slot:" + todayNoSpace + ":" + slotDigest;
|
||||||
|
Integer reusedCounter = null;
|
||||||
|
if (stringRedisTemplate != null && !forceGenerate && total == 1) {
|
||||||
|
String slotVal = stringRedisTemplate.opsForValue().get(slotKey);
|
||||||
|
if (slotVal != null && !slotVal.isEmpty()) {
|
||||||
|
try {
|
||||||
|
int c = Integer.parseInt(slotVal.trim());
|
||||||
|
if (c >= 1) {
|
||||||
|
reusedCounter = c;
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException ignore) {
|
||||||
|
reusedCounter = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int startCount = 1;
|
int startCount = 1;
|
||||||
|
if (reusedCounter != null) {
|
||||||
|
startCount = reusedCounter;
|
||||||
if (stringRedisTemplate != null) {
|
if (stringRedisTemplate != null) {
|
||||||
|
stringRedisTemplate.opsForValue().set(slotKey, String.valueOf(reusedCounter), 1, TimeUnit.DAYS);
|
||||||
|
}
|
||||||
|
} else if (stringRedisTemplate != null) {
|
||||||
try {
|
try {
|
||||||
String s = stringRedisTemplate.opsForValue().get(redisKey);
|
String s = stringRedisTemplate.opsForValue().get(redisKey);
|
||||||
int count = s != null ? Integer.parseInt(s) : 0;
|
int count = s != null ? Integer.parseInt(s) : 0;
|
||||||
startCount = count + 1;
|
startCount = count + 1;
|
||||||
int endCount = count + total;
|
int endCount = count + total;
|
||||||
stringRedisTemplate.opsForValue().set(redisKey, String.valueOf(endCount), 30, TimeUnit.DAYS);
|
stringRedisTemplate.opsForValue().set(redisKey, String.valueOf(endCount), 30, TimeUnit.DAYS);
|
||||||
|
if (total == 1) {
|
||||||
|
stringRedisTemplate.opsForValue().set(slotKey, String.valueOf(startCount), 1, TimeUnit.DAYS);
|
||||||
|
}
|
||||||
} catch (Exception ignore) {
|
} catch (Exception ignore) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1217,6 +1227,26 @@ public class InstructionServiceImpl implements IInstructionService {
|
|||||||
return out.toString();
|
return out.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同日「生」指令槽位键摘要:规范化后的 型号 + 地址,避免仅按地址误伤「同址不同型号」。
|
||||||
|
*/
|
||||||
|
private String digestShengSlot(String model, String address) {
|
||||||
|
String m = normalizeWhitespace(model == null ? "" : model);
|
||||||
|
String a = normalizeWhitespace(address == null ? "" : address);
|
||||||
|
String raw = m + "\u0001" + a;
|
||||||
|
try {
|
||||||
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||||
|
byte[] d = md.digest(raw.getBytes(StandardCharsets.UTF_8));
|
||||||
|
StringBuilder sb = new StringBuilder(32);
|
||||||
|
for (byte b : d) {
|
||||||
|
sb.append(String.format("%02x", b));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Integer.toHexString(Objects.hash(m, a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从分销标记中提取订单编号
|
* 从分销标记中提取订单编号
|
||||||
* 例如:从 "H-TF(10.10 腾锋 JY202510093195)" 中提取 "JY202510093195"
|
* 例如:从 "H-TF(10.10 腾锋 JY202510093195)" 中提取 "JY202510093195"
|
||||||
|
|||||||
@@ -1000,6 +1000,22 @@ public class SocialMediaServiceImpl implements ISocialMediaService
|
|||||||
String cleanTitle = cleanTitleOrRemark(title.trim());
|
String cleanTitle = cleanTitleOrRemark(title.trim());
|
||||||
String cleanRemark = StringUtils.isNotEmpty(remark) ? cleanTitleOrRemark(remark.trim()) : "";
|
String cleanRemark = StringUtils.isNotEmpty(remark) ? cleanTitleOrRemark(remark.trim()) : "";
|
||||||
|
|
||||||
|
boolean generateSeed = isTrue(req.get("generateSeedNote"));
|
||||||
|
if (generateSeed) {
|
||||||
|
if (StringUtils.isEmpty(asString(req.get("goods_title")))) {
|
||||||
|
req.put("goods_title", cleanTitle);
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(asString(req.get("goods_model")))) {
|
||||||
|
req.put("goods_model", cleanRemark);
|
||||||
|
}
|
||||||
|
String seedError = validateSeedRequiredFields(req);
|
||||||
|
if (seedError != null) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("error", seedError);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String wenanBase = getPromptTemplateWithDefault("xianyu:wenan_base", DEFAULT_XIANYU_WENAN_BASE);
|
String wenanBase = getPromptTemplateWithDefault("xianyu:wenan_base", DEFAULT_XIANYU_WENAN_BASE);
|
||||||
String jiaonixiadanExtra = getPromptTemplateWithDefault("xianyu:jiaonixiadan_extra", DEFAULT_XIANYU_JIAONIXIADAN_EXTRA);
|
String jiaonixiadanExtra = getPromptTemplateWithDefault("xianyu:jiaonixiadan_extra", DEFAULT_XIANYU_JIAONIXIADAN_EXTRA);
|
||||||
|
|
||||||
@@ -1028,14 +1044,7 @@ public class SocialMediaServiceImpl implements ISocialMediaService
|
|||||||
result.put("daixiadan", daixiadanBuilder.toString());
|
result.put("daixiadan", daixiadanBuilder.toString());
|
||||||
result.put("jiaonixiadan", jiaonixiadanBuilder.toString());
|
result.put("jiaonixiadan", jiaonixiadanBuilder.toString());
|
||||||
|
|
||||||
boolean generateSeed = isTrue(req.get("generateSeedNote"));
|
|
||||||
if (generateSeed) {
|
if (generateSeed) {
|
||||||
String seedError = validateSeedRequiredFields(req);
|
|
||||||
if (seedError != null) {
|
|
||||||
result.put("success", false);
|
|
||||||
result.put("error", seedError);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
String seedPrompt = buildSeedPrompt(req);
|
String seedPrompt = buildSeedPrompt(req);
|
||||||
String seedNote = callJarvisLlm(seedPrompt, asString(req.get("profileId")));
|
String seedNote = callJarvisLlm(seedPrompt, asString(req.get("profileId")));
|
||||||
@@ -1045,9 +1054,8 @@ public class SocialMediaServiceImpl implements ISocialMediaService
|
|||||||
result.put("seedNote", seedNote.trim());
|
result.put("seedNote", seedNote.trim());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("生成闲鱼种草文案失败", e);
|
log.error("生成闲鱼种草文案失败", e);
|
||||||
result.put("success", false);
|
result.put("seedNote", "");
|
||||||
result.put("error", "种草文案生成失败: " + e.getMessage());
|
result.put("seedNoteError", "种草文案生成失败: " + e.getMessage());
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
Reference in New Issue
Block a user