From 1c518e10a50050d383e714b581c94dea58ec4d67 Mon Sep 17 00:00:00 2001
From: liyong <18434998025@163.com>
Date: 星期五, 22 五月 2026 18:01:34 +0800
Subject: [PATCH] fix(approve): 修复审批实例查询条件及流程控制问题
---
src/main/java/com/ruoyi/ai/assistant/SalesIntentExecutor.java | 270 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 270 insertions(+), 0 deletions(-)
diff --git a/src/main/java/com/ruoyi/ai/assistant/SalesIntentExecutor.java b/src/main/java/com/ruoyi/ai/assistant/SalesIntentExecutor.java
new file mode 100644
index 0000000..4388a3c
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/assistant/SalesIntentExecutor.java
@@ -0,0 +1,270 @@
+package com.ruoyi.ai.assistant;
+
+import com.ruoyi.ai.tools.SalesAgentTools;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.time.LocalDate;
+import java.time.YearMonth;
+import java.time.format.DateTimeFormatter;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@Component
+public class SalesIntentExecutor {
+
+ private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ private static final Pattern LIMIT_PATTERN = Pattern.compile("(鍓峾鏈�杩�)?\\s*(\\d{1,2})\\s*鏉�");
+ private static final Pattern DATE_PATTERN = Pattern.compile("(\\d{4}-\\d{2}-\\d{2})");
+ private static final Pattern RELATIVE_DAY_PATTERN = Pattern.compile("(杩憒鏈�杩�)?\\s*(\\d{1,3})\\s*澶�");
+
+ private final SalesAgentTools salesAgentTools;
+
+ public SalesIntentExecutor(SalesAgentTools salesAgentTools) {
+ this.salesAgentTools = salesAgentTools;
+ }
+
+ public String tryExecute(String memoryId, String message) {
+ if (!StringUtils.hasText(message)) {
+ return null;
+ }
+ String text = message.trim();
+
+ String quickPromptResponse = tryExecuteQuickPrompt(memoryId, text);
+ if (StringUtils.hasText(quickPromptResponse)) {
+ return quickPromptResponse;
+ }
+
+ String keyword = extractKeyword(text);
+ Integer limit = extractLimit(text);
+ DateRange dateRange = extractDateRange(text);
+ String startDate = dateRange.startDate();
+ String endDate = dateRange.endDate();
+
+ if (containsAny(text, "娴佸け", "娴佸け椋庨櫓", "瀹㈡埛娴佸け", "椋庨櫓鍒嗘瀽")) {
+ return salesAgentTools.analyzeCustomerChurnRisk(memoryId, startDate, endDate, text, keyword, limit);
+ }
+ if (containsAny(text, "鍥炴", "鏀舵", "鎶ヤ环")
+ && containsAny(text, "寤鸿", "绛栫暐", "浼樺寲", "鏂规")) {
+ return salesAgentTools.suggestCollectionAndQuotationStrategy(
+ memoryId, startDate, endDate, text, keyword, limit, shouldPrioritizeHighRisk(text));
+ }
+ if (containsAny(text, "鎸囨爣", "缁熻", "鐪嬫澘", "鎬昏", "缁忚惀鍒嗘瀽")) {
+ return salesAgentTools.getSalesDashboard(memoryId, startDate, endDate, text);
+ }
+ if (containsAny(text, "瀹㈡埛妗f", "绉佹捣", "鍏捣", "瀹㈡埛姹�")) {
+ return salesAgentTools.listCustomerProfiles(memoryId, extractSeaType(text), keyword, limit);
+ }
+ if (containsAny(text, "閿�鍞姤浠�", "鎶ヤ环鍗�", "鎶ヤ环", "璇环")) {
+ return salesAgentTools.listSalesQuotations(memoryId, keyword, startDate, endDate, limit);
+ }
+ if (containsAny(text, "閿�鍞��璐�", "閫�璐�", "閫�娆�")) {
+ return salesAgentTools.listSalesReturns(memoryId, startDate, endDate, keyword, limit);
+ }
+ if (containsAny(text, "瀹㈡埛寰�鏉�", "寰�鏉�", "鍥炴", "搴旀敹", "鏉ユ", "鏀舵鏄庣粏")) {
+ return salesAgentTools.listCustomerInteractions(memoryId, keyword, startDate, endDate, limit);
+ }
+ if (containsAny(text, "鍙戣揣鍙拌处", "鍙戣揣", "鐗╂祦", "蹇��", "杩愯緭")) {
+ return salesAgentTools.listShippingLedgers(memoryId, keyword, startDate, endDate, limit);
+ }
+ if (containsAny(text, "閿�鍞彴璐�", "閿�鍞悎鍚�", "閿�鍞鍗�", "鍚堝悓鍙拌处", "璁㈠崟鍙拌处")) {
+ return salesAgentTools.listSalesLedgers(memoryId, keyword, startDate, endDate, limit);
+ }
+ return null;
+ }
+
+ private String tryExecuteQuickPrompt(String memoryId, String text) {
+ String normalized = normalizeForMatch(text);
+ if ("鏌ヨ绉佹捣瀹㈡埛妗f鍓�10鏉�".equals(normalized)) {
+ return salesAgentTools.listCustomerProfiles(memoryId, "private", null, 10);
+ }
+ if ("鏌ヨ鍏捣瀹㈡埛妗f".equals(normalized)) {
+ return salesAgentTools.listCustomerProfiles(memoryId, "public", null, 10);
+ }
+ if ("鏌ヨ鏈湀閿�鍞姤浠�".equals(normalized)) {
+ DateRange range = monthRange();
+ return salesAgentTools.listSalesQuotations(memoryId, null, range.startDate(), range.endDate(), 10);
+ }
+ if ("鏌ヨ鏈湀閿�鍞彴璐�".equals(normalized)) {
+ DateRange range = monthRange();
+ return salesAgentTools.listSalesLedgers(memoryId, null, range.startDate(), range.endDate(), 10);
+ }
+ if ("鏌ヨ杩�30澶╅攢鍞��璐�".equals(normalized)) {
+ DateRange range = recentDaysRange(30);
+ return salesAgentTools.listSalesReturns(memoryId, range.startDate(), range.endDate(), null, 10);
+ }
+ if ("鏌ヨ杩�30澶╁鎴峰洖娆惧線鏉�".equals(normalized)) {
+ DateRange range = recentDaysRange(30);
+ return salesAgentTools.listCustomerInteractions(memoryId, null, range.startDate(), range.endDate(), 10);
+ }
+ if ("鏌ヨ鏈湀鍙戣揣鍙拌处".equals(normalized)) {
+ DateRange range = monthRange();
+ return salesAgentTools.listShippingLedgers(memoryId, null, range.startDate(), range.endDate(), 10);
+ }
+ if ("鏌ョ湅閿�鍞寚鏍囩粺璁�".equals(normalized)) {
+ return salesAgentTools.getSalesDashboard(memoryId, null, null, "鏈湀");
+ }
+ if ("甯垜鍋氬鎴锋祦澶遍闄╁垎鏋愯繎30澶╁墠20鏉�".equals(normalized)) {
+ DateRange range = recentDaysRange(30);
+ return salesAgentTools.analyzeCustomerChurnRisk(memoryId, range.startDate(), range.endDate(), "杩�30澶�", null, 20);
+ }
+ if ("鐢熸垚鍥炴涓庢姤浠风瓥鐣ュ缓璁紭鍏堥珮椋庨櫓瀹㈡埛".equals(normalized)) {
+ DateRange range = recentDaysRange(30);
+ return salesAgentTools.suggestCollectionAndQuotationStrategy(memoryId, range.startDate(), range.endDate(), "杩�30澶�", null, 10, true);
+ }
+ return null;
+ }
+
+ private boolean containsAny(String text, String... keywords) {
+ for (String keyword : keywords) {
+ if (text.contains(keyword)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private String extractSeaType(String text) {
+ if (text.contains("鍏捣")) {
+ return "public";
+ }
+ if (text.contains("绉佹捣")) {
+ return "private";
+ }
+ return null;
+ }
+
+ private Integer extractLimit(String text) {
+ Matcher matcher = LIMIT_PATTERN.matcher(text);
+ return matcher.find() ? Integer.parseInt(matcher.group(2)) : 10;
+ }
+
+ private DateRange extractDateRange(String text) {
+ Matcher matcher = DATE_PATTERN.matcher(text);
+ if (matcher.find()) {
+ String first = matcher.group(1);
+ String second = matcher.find() ? matcher.group(1) : first;
+ return buildDateRange(first, second);
+ }
+ if (text.contains("鏈湀")) {
+ return monthRange();
+ }
+ if (text.contains("涓婃湀")) {
+ return lastMonthRange();
+ }
+ if (text.contains("鏈勾") || text.contains("浠婂勾")) {
+ return yearRange();
+ }
+ Matcher relativeDayMatcher = RELATIVE_DAY_PATTERN.matcher(text);
+ if (relativeDayMatcher.find()) {
+ int days = Integer.parseInt(relativeDayMatcher.group(2));
+ return recentDaysRange(days);
+ }
+ return new DateRange(null, null);
+ }
+
+ private DateRange buildDateRange(String start, String end) {
+ LocalDate startDate = parseDate(start);
+ LocalDate endDate = parseDate(end);
+ if (startDate == null || endDate == null) {
+ return new DateRange(null, null);
+ }
+ if (startDate.isAfter(endDate)) {
+ LocalDate temp = startDate;
+ startDate = endDate;
+ endDate = temp;
+ }
+ return new DateRange(formatDate(startDate), formatDate(endDate));
+ }
+
+ private DateRange recentDaysRange(int days) {
+ LocalDate end = LocalDate.now();
+ int safeDays = Math.max(days, 1);
+ LocalDate start = end.minusDays(safeDays - 1L);
+ return new DateRange(formatDate(start), formatDate(end));
+ }
+
+ private DateRange monthRange() {
+ LocalDate today = LocalDate.now();
+ return new DateRange(formatDate(today.withDayOfMonth(1)), formatDate(today));
+ }
+
+ private DateRange lastMonthRange() {
+ YearMonth lastMonth = YearMonth.now().minusMonths(1);
+ return new DateRange(formatDate(lastMonth.atDay(1)), formatDate(lastMonth.atEndOfMonth()));
+ }
+
+ private DateRange yearRange() {
+ LocalDate today = LocalDate.now();
+ return new DateRange(formatDate(today.withDayOfYear(1)), formatDate(today));
+ }
+
+ private LocalDate parseDate(String text) {
+ try {
+ return LocalDate.parse(text, DATE_FMT);
+ } catch (Exception ignored) {
+ return null;
+ }
+ }
+
+ private String formatDate(LocalDate date) {
+ return date == null ? null : date.format(DATE_FMT);
+ }
+
+ private String normalizeForMatch(String text) {
+ if (!StringUtils.hasText(text)) {
+ return "";
+ }
+ return text.replace("锛�", "")
+ .replace(",", "")
+ .replace("銆�", "")
+ .replace(".", "")
+ .replace("锛�", "")
+ .replace("!", "")
+ .replace("锛�", "")
+ .replace("?", "")
+ .replace("锛�", "")
+ .replace(":", "")
+ .replace("锛�", "")
+ .replace(";", "")
+ .replace(" ", "")
+ .trim();
+ }
+
+ private Boolean shouldPrioritizeHighRisk(String text) {
+ return containsAny(text, "浼樺厛楂橀闄�", "楂橀闄╁鎴�", "楂橀闄�");
+ }
+
+ private String extractKeyword(String text) {
+ String cleaned = text
+ .replace("鏌ヨ", "")
+ .replace("鏌ョ湅", "")
+ .replace("鐪嬩笅", "")
+ .replace("鐪嬬湅", "")
+ .replace("甯垜", "")
+ .replace("璇�", "")
+ .replace("涓�涓�", "")
+ .replace("閿�鍞�", "")
+ .replace("瀹㈡埛妗f", "")
+ .replace("鎶ヤ环鍗�", "")
+ .replace("閿�鍞姤浠�", "")
+ .replace("閿�鍞彴璐�", "")
+ .replace("鍙戣揣鍙拌处", "")
+ .replace("瀹㈡埛寰�鏉�", "")
+ .replace("閿�鍞��璐�", "")
+ .replace("鍓�10鏉�", "")
+ .replace("鏈�杩�10鏉�", "")
+ .replace("鍓�20鏉�", "")
+ .replace("鏈�杩�20鏉�", "")
+ .replace("杩�30澶�", "")
+ .replace("鏈湀", "")
+ .replace("鏈勾", "")
+ .replace("浠婂勾", "")
+ .replace("鏉�", "")
+ .trim();
+ return cleaned.length() >= 2 ? cleaned : null;
+ }
+
+ private record DateRange(String startDate, String endDate) {
+ }
+}
--
Gitblit v1.9.3