5 天以前 482b2982ba27b18e6391c3862ec239c89a801a46
src/main/java/com/ruoyi/ai/assistant/PurchaseIntentExecutor.java
@@ -4,6 +4,10 @@
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -13,6 +17,8 @@
    private static final Pattern ID_PATTERN = Pattern.compile("\\b\\d{1,12}\\b");
    private static final Pattern LIMIT_PATTERN = Pattern.compile("(前|最近)?(\\d{1,2})条");
    private static final Pattern DATE_PATTERN = Pattern.compile("\\d{4}-\\d{2}-\\d{2}");
    private static final Pattern RELATIVE_RANGE_PATTERN = Pattern.compile("(近|最近)(\\d+)(天|周|个月|月|年)");
    private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    private final PurchaseAgentTools purchaseAgentTools;
@@ -25,32 +31,80 @@
            return null;
        }
        String text = message.trim();
        String startDate = extractStartDate(text);
        String endDate = extractEndDate(text);
        Integer limit = extractLimit(text);
        if (containsAny(text, "排行", "排名", "前几", "前五", "前十") && containsAny(text, "物料", "产品", "原材料", "采购金额", "金额")) {
            return purchaseAgentTools.rankPurchaseMaterials(
                    memoryId,
                    startDate,
                    endDate,
                    text,
                    limit
            );
        }
        if (containsAny(text, "未入库", "待入库", "没有入库", "还未入库")) {
            return purchaseAgentTools.listUnstockedPurchaseOrders(
                    memoryId,
                    startDate,
                    endDate,
                    extractKeyword(text),
                    limit
            );
        }
        if (containsAny(text, "到货异常", "到货有异常", "异常到货", "到货问题", "供应商到货异常")) {
            return purchaseAgentTools.listArrivalExceptions(
                    memoryId,
                    startDate,
                    endDate,
                    text,
                    limit
            );
        }
        if (containsAny(text, "待付款", "未付款", "未付清", "待支付", "应付")) {
            return purchaseAgentTools.listPendingPaymentOrders(
                    memoryId,
                    startDate,
                    endDate,
                    extractKeyword(text),
                    limit
            );
        }
        if (containsAny(text, "退货", "退料", "拒收")) {
            return purchaseAgentTools.listPurchaseReturns(
                    memoryId,
                    startDate,
                    endDate,
                    extractKeyword(text),
                    limit
            );
        }
        if (isStatsIntent(text)) {
            return purchaseAgentTools.getPurchaseStats(
                    memoryId,
                    extractStartDate(text),
                    extractEndDate(text),
                    startDate,
                    endDate,
                    text
            );
        }
        if (containsAny(text, "详情", "明细") && extractId(text) != null) {
            return purchaseAgentTools.getPurchaseLedgerDetail(memoryId, extractId(text));
        }
        if (containsAny(text, "台账", "采购单", "合同", "列表", "查询")) {
        if (containsAny(text, "台账", "采购单", "采购订单", "订单", "合同", "列表", "查询")) {
            return purchaseAgentTools.listPurchaseLedgers(
                    memoryId,
                    extractKeyword(text),
                    extractStartDate(text),
                    extractEndDate(text),
                    extractLimit(text)
                    startDate,
                    endDate,
                    limit
            );
        }
        return null;
    }
    private boolean isStatsIntent(String text) {
        if (containsAny(text, "统计", "分析", "报表", "汇总", "趋势", "数据看板")) {
        if (containsAny(text, "统计", "分析", "报表", "汇总", "趋势", "数据看板", "情况", "有多少")) {
            return true;
        }
        boolean queryWord = containsAny(text, "查询", "查看", "看下", "看看", "获取");
@@ -84,13 +138,18 @@
    private String extractStartDate(String text) {
        Matcher matcher = DATE_PATTERN.matcher(text);
        return matcher.find() ? matcher.group() : null;
        if (matcher.find()) {
            return matcher.group();
        }
        DateRange range = extractRelativeDateRange(text);
        return range == null ? null : range.start().format(DATE_FMT);
    }
    private String extractEndDate(String text) {
        Matcher matcher = DATE_PATTERN.matcher(text);
        if (!matcher.find()) {
            return null;
            DateRange range = extractRelativeDateRange(text);
            return range == null ? null : range.end().format(DATE_FMT);
        }
        return matcher.find() ? matcher.group() : null;
    }
@@ -100,11 +159,103 @@
                .replace("查询", "")
                .replace("查看", "")
                .replace("采购", "")
                .replace("采购单", "")
                .replace("采购订单", "")
                .replace("订单", "")
                .replace("今年", "")
                .replace("本年", "")
                .replace("去年", "")
                .replace("本月", "")
                .replace("上月", "")
                .replace("本周", "")
                .replace("上周", "")
                .replace("今天", "")
                .replace("昨天", "")
                .replace("近半年", "")
                .replace("最近半年", "")
                .replace("最近半个月", "")
                .replace("半个月", "")
                .replace("台账", "")
                .replace("列表", "")
                .replace("哪些", "")
                .replace("什么", "")
                .replace("情况", "")
                .replace("有没有", "")
                .replace("有啥", "")
                .replace("有无", "")
                .replace("列出", "")
                .replace("帮我", "")
                .replace("给我", "")
                .replace("我", "")
                .replace("最近10条", "")
                .replace("前10条", "")
                .trim();
        cleaned = DATE_PATTERN.matcher(cleaned).replaceAll("");
        cleaned = RELATIVE_RANGE_PATTERN.matcher(cleaned).replaceAll("");
        return cleaned.length() >= 2 ? cleaned : null;
    }
    private DateRange extractRelativeDateRange(String text) {
        if (!StringUtils.hasText(text)) {
            return null;
        }
        String normalized = text.toLowerCase(Locale.ROOT);
        LocalDate today = LocalDate.now();
        if (normalized.contains("今天")) {
            return new DateRange(today, today);
        }
        if (normalized.contains("昨天")) {
            LocalDate yesterday = today.minusDays(1);
            return new DateRange(yesterday, yesterday);
        }
        if (normalized.contains("今年") || normalized.contains("本年")) {
            return new DateRange(today.withDayOfYear(1), today);
        }
        if (normalized.contains("去年")) {
            LocalDate first = today.minusYears(1).withDayOfYear(1);
            LocalDate last = first.withDayOfYear(first.lengthOfYear());
            return new DateRange(first, last);
        }
        if (normalized.contains("本月")) {
            return new DateRange(today.withDayOfMonth(1), today);
        }
        if (normalized.contains("上月")) {
            LocalDate first = today.minusMonths(1).withDayOfMonth(1);
            LocalDate last = first.withDayOfMonth(first.lengthOfMonth());
            return new DateRange(first, last);
        }
        if (normalized.contains("本周")) {
            LocalDate weekStart = today.with(DayOfWeek.MONDAY);
            return new DateRange(weekStart, today);
        }
        if (normalized.contains("上周")) {
            LocalDate weekStart = today.with(DayOfWeek.MONDAY).minusWeeks(1);
            return new DateRange(weekStart, weekStart.plusDays(6));
        }
        if (normalized.contains("近半年") || normalized.contains("最近半年")) {
            return new DateRange(today.minusMonths(6).plusDays(1), today);
        }
        if (normalized.contains("近半个月") || normalized.contains("最近半个月") || normalized.contains("半个月")) {
            return new DateRange(today.minusDays(14), today);
        }
        Matcher matcher = RELATIVE_RANGE_PATTERN.matcher(normalized);
        if (matcher.find()) {
            int amount = Integer.parseInt(matcher.group(2));
            String unit = matcher.group(3);
            LocalDate start = switch (unit) {
                case "天" -> today.minusDays(Math.max(amount - 1L, 0));
                case "周" -> today.minusWeeks(Math.max(amount, 1)).plusDays(1);
                case "个月", "月" -> today.minusMonths(Math.max(amount, 1)).plusDays(1);
                case "年" -> today.minusYears(Math.max(amount, 1)).plusDays(1);
                default -> today.minusDays(29);
            };
            return new DateRange(start, today);
        }
        return null;
    }
    private record DateRange(LocalDate start, LocalDate end) {
    }
}