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 278c7e8..d1f5e54 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 @@ -81,7 +81,7 @@ public class InstructionServiceImpl implements IInstructionService { List result; if (command == null || command.trim().isEmpty()) { - result = Collections.singletonList("请输入指令"); + result = Collections.singletonList("「指令」\n\n请发送具体指令内容;不确定可发「京菜单」查看列表。"); } else { String input = command.trim(); @@ -1450,7 +1450,8 @@ public class InstructionServiceImpl implements IInstructionService { */ private String buildDanRecordSuccessMessage(JDOrder order, String originalInput) { StringBuilder sb = new StringBuilder(); - sb.append("录单成功\n"); + sb.append("「录单」已成功\n"); + sb.append("————————————\n"); sb.append("单号:").append(nvl(order.getRemark())).append("\n"); sb.append("订单号:").append(nvl(order.getOrderId())).append("\n"); if (!isEmpty(order.getThirdPartyOrderNo())) { @@ -2031,13 +2032,26 @@ public class InstructionServiceImpl implements IInstructionService { // ===== 工具 ===== private String jingMenu() { - StringBuilder content = new StringBuilder(); - content.append("菜单:京+命令,如: 京今日统计\r\n").append("今日统计\r\n").append("昨日统计\r\n").append("七日统计\r\n").append("一个月统计\r\n").append("两个月统计\r\n").append("三个月统计\r\n").append("总统计\r\n").append("这个月统计\r\n").append("上个月统计\r\n").append("\r\n").append("今日订单\r\n").append("昨日订单\r\n").append("七日订单\r\n"); - return content.toString(); + return "「京粉 · 菜单」\n\n" + + "企微/机器人前请加「京」,例如:京今日统计\n\n" + + "—— 统计 ——\n" + + "今日统计、昨日统计、三日统计、七日统计\n" + + "一个月统计、两个月统计、三个月统计\n" + + "这个月统计、上个月统计、总统计\n\n" + + "—— 订单 ——\n" + + "今日订单、昨日订单、七日订单\n\n" + + "发「京」单独或「京菜单」可再次打开本列表。"; } private String helpText() { - return "可用指令示例:\n" + "1) 京菜单(查看所有可用命令)\n" + "2) 京今日统计 / 京昨日统计 / 京七日统计 / 京一个月统计 等\n" + "3) 京今日订单 / 京昨日订单 / 京七日订单\n" + "4) 慢搜 关键词 / 慢查 关键词(从录单库模糊查询)\n" + "5) 录单20250101-20250107 或 录单昨日|三日|七日(仅查询导出)\n" + "\n提示:转链与礼金请前往‘一键转链’页面使用。"; + return "「指令帮助」\n\n" + + "常用示例:\n" + + "· 京菜单 — 查看统计与订单类命令\n" + + "· 京今日统计 / 京昨日统计 / 京七日统计 …\n" + + "· 京今日订单 / 京昨日订单 / 京七日订单\n" + + "· 慢搜 关键词、慢查 关键词(录单库模糊查询)\n" + + "· 录单20250101-20250107 或 录单昨日|三日|七日(导出)\n\n" + + "说明:转链、礼金等请使用系统内「一键转链」页面。"; } private LocalDateTime effectiveToday() { diff --git a/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/WeComInboundServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/WeComInboundServiceImpl.java index 651de82..f2ba0b2 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/WeComInboundServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/WeComInboundServiceImpl.java @@ -32,6 +32,48 @@ public class WeComInboundServiceImpl implements IWeComInboundService { private static final Pattern JD_3CN = Pattern.compile("https://3\\.cn/[A-Za-z0-9\\-]+"); private static final int REPLY_MAX_LEN = 3500; + private static final String REPLY_TRUNCATED_HINT = "\n…\n(内容过长,余下部分已省略)"; + + /** 无超级管理员配置 */ + private static String replyPermissionDenied() { + return "「权限说明」\n\n" + + "当前企微账号尚未授权使用本机器人。\n\n" + + "请管理员在后台打开「超级管理员」,任选一种方式:\n" + + "· 将您的企微 UserID 填入 wxid;或\n" + + "· 将您的 UserID 写入某一行的 touser(多个用英文逗号分隔)。"; + } + + /** 已授权但非 LinPingFan:可发送的内容范围 */ + private static String replyGeneralUserScopeHint() { + return "「发送范围」\n\n" + + "当前账号支持:\n" + + "· 「京」开头的统计、订单类指令(可先发「京菜单」查看列表)\n" + + "· 含 3.cn 的京东物流分享:先发链接,再发备注\n" + + "· 以「单」或「开始」开头,且含「分销标记」的录单正文\n\n" + + "如需其他指令,请联系管理员。"; + } + + /** 用户取消物流多轮 */ + private static String replyLogisticsCancelled() { + return "「物流录入」已取消\n\n" + + "可重新发送含 3.cn 的分享链接,开始新的一轮。"; + } + + /** 已收到链接,等待备注 */ + private static String replyLogisticsWaitRemark(String shortUrl) { + String link = shortUrl != null ? shortUrl : ""; + return "「物流链接」已收到\n" + + link + "\n\n" + + "请在下一条消息中发送该单的备注。\n" + + "若需放弃本轮,请回复「取消」或「取消录入」。"; + } + + /** 备注已提交并入队 */ + private static String replyLogisticsRemarkDone() { + return "「物流备注」已登记\n\n" + + "已加入查询队列,约每 10 分钟扫描并推送结果(与订单物流任务一致)。\n" + + "本轮录入已结束,可继续发录单、指令或新的物流链接。"; + } @Resource private SuperAdminService superAdminService; @@ -53,7 +95,7 @@ public class WeComInboundServiceImpl implements IWeComInboundService { SuperAdmin row = superAdminService.selectSuperAdminByWecomUserId(from); boolean isSuper = WE_COM_SUPER_USER_ID.equals(from); if (!isSuper && row == null) { - return "无权限:请在后台「超级管理员」将您的企微 UserID 填到 wxid,或加入该行的 touser(逗号分隔)"; + return replyPermissionDenied(); } final boolean danRecordPriority = isDanRecordPriorityOverLogistics(content); @@ -68,16 +110,24 @@ public class WeComInboundServiceImpl implements IWeComInboundService { String t = content.trim(); if ("取消".equals(t) || "取消录入".equals(t)) { weComChatSessionService.delete(from); - return "已取消物流链接录入"; + return replyLogisticsCancelled(); } if (danRecordPriority) { weComChatSessionService.delete(from); log.info("企微用户 {} 在录单优先下退出物流备注会话", from); } else if (isJdShareLogisticsMessage(content)) { String url = extractJd3cnUrl(content); + if (url != null && url.equals(session.getLogisticsUrl())) { + // 备注里夹带同一条 3.cn(整段分享文案),不得再占着「待备注」会话 + weComChatSessionService.delete(from); + String touser = resolveTouser(row, isSuper); + log.info("企微物流会话备注(含同款链接)提交 user={} url={} remarkLen={}", from, url, t.length()); + logisticsService.enqueueShareLinkForScan(url, content.trim(), touser); + return replyLogisticsRemarkDone(); + } if (url != null) { weComChatSessionService.put(from, WeComChatSession.startLogisticsWaitRemark(url)); - return "收到物流链接 " + url + " ,请输入备注信息"; + return replyLogisticsWaitRemark(url); } } else if (t.startsWith("京")) { weComChatSessionService.delete(from); @@ -88,7 +138,7 @@ public class WeComInboundServiceImpl implements IWeComInboundService { String touser = resolveTouser(row, isSuper); log.info("企微物流会话提交备注 user={} url={} remarkLen={}", from, url, t.length()); logisticsService.enqueueShareLinkForScan(url, content.trim(), touser); - return "已登记备注,物流将随定时任务查询并推送(与订单物流扫描一致,约每10分钟)"; + return replyLogisticsRemarkDone(); } } @@ -97,14 +147,14 @@ public class WeComInboundServiceImpl implements IWeComInboundService { if (url != null) { weComChatSessionService.put(from, WeComChatSession.startLogisticsWaitRemark(url)); log.info("企微物流多轮会话已创建 user={} url={}", from, url); - return "收到物流链接 " + url + " ,请输入备注信息"; + return replyLogisticsWaitRemark(url); } } if (!isSuper) { String cmd = content.trim(); if (!cmd.startsWith("京") && !danRecordPriority) { - return "当前账号仅支持:以「京」开头的指令,或发送含 3.cn 京东物流分享链接,或以「单/开始」开头且含「分销标记」的录单"; + return replyGeneralUserScopeHint(); } } @@ -114,7 +164,7 @@ public class WeComInboundServiceImpl implements IWeComInboundService { } String reply = String.join("\n", parts); if (reply.length() > REPLY_MAX_LEN) { - reply = reply.substring(0, REPLY_MAX_LEN) + "\n...(截断)"; + reply = reply.substring(0, REPLY_MAX_LEN) + REPLY_TRUNCATED_HINT; } return reply; }