From a22d17de73e081e0fcd0f0b4de744d4fc3930e92 Mon Sep 17 00:00:00 2001 From: van Date: Tue, 7 Apr 2026 17:29:32 +0800 Subject: [PATCH] 1 --- .../service/impl/InstructionServiceImpl.java | 68 +++++++++++++------ .../service/impl/SocialMediaServiceImpl.java | 28 +++++--- 2 files changed, 67 insertions(+), 29 deletions(-) diff --git a/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/InstructionServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/InstructionServiceImpl.java index 05ea4c0..dae8599 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/InstructionServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/InstructionServiceImpl.java @@ -12,6 +12,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; @@ -1147,24 +1149,6 @@ public class InstructionServiceImpl implements IInstructionService { 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 todayNoSpace = today.trim(); String keyWithSpace = "order_count:" + today; // 带空格 @@ -1188,14 +1172,40 @@ public class InstructionServiceImpl implements IInstructionService { StringBuilder out = new StringBuilder(); 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; - if (stringRedisTemplate != null) { + if (reusedCounter != null) { + startCount = reusedCounter; + if (stringRedisTemplate != null) { + stringRedisTemplate.opsForValue().set(slotKey, String.valueOf(reusedCounter), 1, TimeUnit.DAYS); + } + } else if (stringRedisTemplate != null) { try { String s = stringRedisTemplate.opsForValue().get(redisKey); int count = s != null ? Integer.parseInt(s) : 0; startCount = count + 1; int endCount = count + total; 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) { } } @@ -1217,6 +1227,26 @@ public class InstructionServiceImpl implements IInstructionService { 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" diff --git a/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/SocialMediaServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/SocialMediaServiceImpl.java index e884277..660b291 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/SocialMediaServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/SocialMediaServiceImpl.java @@ -1000,6 +1000,22 @@ public class SocialMediaServiceImpl implements ISocialMediaService String cleanTitle = cleanTitleOrRemark(title.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 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("jiaonixiadan", jiaonixiadanBuilder.toString()); - boolean generateSeed = isTrue(req.get("generateSeedNote")); if (generateSeed) { - String seedError = validateSeedRequiredFields(req); - if (seedError != null) { - result.put("success", false); - result.put("error", seedError); - return result; - } try { String seedPrompt = buildSeedPrompt(req); String seedNote = callJarvisLlm(seedPrompt, asString(req.get("profileId"))); @@ -1045,9 +1054,8 @@ public class SocialMediaServiceImpl implements ISocialMediaService result.put("seedNote", seedNote.trim()); } catch (Exception e) { log.error("生成闲鱼种草文案失败", e); - result.put("success", false); - result.put("error", "种草文案生成失败: " + e.getMessage()); - return result; + result.put("seedNote", ""); + result.put("seedNoteError", "种草文案生成失败: " + e.getMessage()); } } return result;