5 天以前 0d7d874912d0147376826b55667a1deb6547ed91
src/main/java/com/ruoyi/ai/service/PurchaseAiService.java
@@ -1,5 +1,6 @@
package com.ruoyi.ai.service;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -55,6 +56,8 @@
    private static final int MAX_FILE_COUNT = 10;
    private static final int MAX_SINGLE_FILE_TEXT_LENGTH = 8000;
    private static final int MAX_TOTAL_FILE_TEXT_LENGTH = 30000;
    private static final DateTimeFormatter CURRENT_DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    private static final ZoneId CHINA_ZONE_ID = ZoneId.of("Asia/Shanghai");
    private final PurchaseAgent purchaseAgent;
    private final PurchaseIntentExecutor purchaseIntentExecutor;
@@ -122,7 +125,17 @@
            return Flux.just(directResponse);
        }
        return purchaseAgent.chat(memoryId, userMessage)
        if (isPurchaseBusinessIntent(userMessage)) {
            String noGuessResponse = buildNoGuessResponse();
            mongoChatMemoryStore.appendMessages(
                    memoryId,
                    List.of(UserMessage.from(userMessage), AiMessage.from(noGuessResponse))
            );
            aiChatSessionService.refreshSessionStats(memoryId, loginUser);
            return Flux.just(noGuessResponse);
        }
        return purchaseAgent.chat(memoryId, userMessage, currentDateForPrompt())
                .doOnComplete(() -> aiChatSessionService.refreshSessionStats(memoryId, loginUser))
                .doOnError(ex -> aiChatSessionService.refreshSessionStats(memoryId, loginUser));
    }
@@ -184,10 +197,10 @@
                    .doOnError(ex -> aiChatSessionService.refreshSessionStats(finalMemoryId, loginUser));
        }
        return Flux.defer(() -> purchaseAgent.chat(finalMemoryId, userPrompt))
        return Flux.defer(() -> purchaseAgent.chat(finalMemoryId, userPrompt, currentDateForPrompt()))
                .onErrorResume(NoSuchElementException.class, ex -> {
                    mongoChatMemoryStore.deleteMessages(finalMemoryId);
                    return purchaseAgent.chat(finalMemoryId, userPrompt);
                    return purchaseAgent.chat(finalMemoryId, userPrompt, currentDateForPrompt());
                })
                .doOnComplete(() -> aiChatSessionService.refreshSessionStats(finalMemoryId, loginUser))
                .doOnError(ex -> aiChatSessionService.refreshSessionStats(finalMemoryId, loginUser));
@@ -455,6 +468,51 @@
        };
    }
    private String currentDateForPrompt() {
        return LocalDate.now(CHINA_ZONE_ID).format(CURRENT_DATE_FMT);
    }
    private boolean isPurchaseBusinessIntent(String message) {
        if (!StringUtils.hasText(message)) {
            return false;
        }
        String text = message.trim();
        boolean hasDomainWord = containsAny(text,
                "采购", "采购台账", "采购单", "采购订单", "供应商", "物料", "入库", "到货", "待付款",
                "付款", "退货", "退料", "发票", "合同");
        boolean hasIntentWord = containsAny(text,
                "查询", "查看", "统计", "分析", "排行", "排名", "列出", "有哪些", "情况", "明细", "详情", "报表");
        return hasDomainWord && hasIntentWord;
    }
    private boolean containsAny(String text, String... keywords) {
        for (String keyword : keywords) {
            if (text.contains(keyword)) {
                return true;
            }
        }
        return false;
    }
    private String buildNoGuessResponse() {
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("success", false);
        result.put("type", "purchase_intent_not_recognized");
        result.put("description", "未识别到可执行的采购查询条件。为保证结果准确,当前不会推测或编造数据,请补充明确时间范围、供应商、采购合同号或物料后再查询。");
        result.put("summary", Map.of());
        result.put("data", Map.of(
                "quickPrompts", List.of(
                        "本月采购金额排名前十的物料有哪些?",
                        "哪些采购订单还未入库?",
                        "最近7天供应商到货异常有哪些?",
                        "帮我统计待付款采购单!",
                        "列出本月采购退货情况"
                )
        ));
        result.put("charts", Map.of());
        return JSON.toJSONString(result);
    }
    private String buildPurchaseFileAnalyzePrompt(String message, String fileContent) {
        return """
                你是采购业务文件分析助手。请严格根据用户上传的多个文件和用户要求提取采购业务数据。