From d640da3dac5b5f811284ab9a7c386da1e7ab6739 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期四, 30 四月 2026 17:30:57 +0800
Subject: [PATCH] feat(ai): 增强AI文件提取和审批待办功能

---
 src/main/java/com/ruoyi/ai/assistant/ApproveTodoIntentExecutor.java |   71 +++++++++++++++++++++++++++--------
 1 files changed, 54 insertions(+), 17 deletions(-)

diff --git a/src/main/java/com/ruoyi/ai/assistant/ApproveTodoIntentExecutor.java b/src/main/java/com/ruoyi/ai/assistant/ApproveTodoIntentExecutor.java
index daaaf74..9f8499d 100644
--- a/src/main/java/com/ruoyi/ai/assistant/ApproveTodoIntentExecutor.java
+++ b/src/main/java/com/ruoyi/ai/assistant/ApproveTodoIntentExecutor.java
@@ -18,6 +18,9 @@
     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 NUMBER_PATTERN = Pattern.compile("(\\d+(?:\\.\\d+)?)");
+    private static final Pattern RECENT_RANGE_PATTERN = Pattern.compile("杩慭\d+(澶﹟鍛▅涓湀|鏈坾骞�)");
+    private static final Pattern HALF_RANGE_PATTERN = Pattern.compile("(鏈�杩憒杩�)?鍗�(涓�)?(鏈坾骞�)");
+    private static final Pattern EXPLICIT_RANGE_PATTERN = Pattern.compile(".*(鍒皘鑷�).*");
 
     private final ApproveTodoTools approveTodoTools;
 
@@ -33,7 +36,7 @@
         String text = message.trim();
         String approveId = extractApproveId(text);
 
-        if (containsAny(text, "缁熻", "鍒嗘瀽", "鍥捐〃", "瓒嬪娍", "鍗犳瘮")) {
+        if (isStatsIntent(text)) {
             return approveTodoTools.getTodoStats(
                     memoryId,
                     extractStartDate(text),
@@ -41,7 +44,7 @@
                     extractTimeRange(text)
             );
         }
-        if (containsAny(text, "娴佽浆", "杩涘害", "鑺傜偣", "鏃ュ織")) {
+        if (containsAny(text, "娴佽浆", "杩涘害", "鑺傜偣", "鏃ュ織", "鍗″湪", "鍗″埌", "褰撳墠瀹℃壒浜�", "澶勭悊璁板綍")) {
             return StringUtils.hasText(approveId)
                     ? approveTodoTools.getTodoProgress(memoryId, approveId)
                     : missingApproveId("todo_progress", "鏌ヨ瀹℃壒杩涘害闇�瑕佹彁渚涙祦绋嬬紪鍙枫��");
@@ -51,19 +54,20 @@
                     ? approveTodoTools.getTodoDetail(memoryId, approveId)
                     : missingApproveId("todo_detail", "鏌ヨ瀹℃壒璇︽儏闇�瑕佹彁渚涙祦绋嬬紪鍙枫��");
         }
-        if (containsAny(text, "鍙栨秷瀹℃牳", "鎾ら攢瀹℃牳", "鍥為��瀹℃牳")) {
+        if (containsAny(text, "鍙栨秷瀹℃牳", "鎾ら攢瀹℃牳", "鍥為��瀹℃牳", "鎾ら攢瀹℃壒", "鎾ゅ洖瀹℃壒")
+                || (containsAny(text, "鎾ら攢", "鎾ゅ洖") && containsAny(text, "瀹℃壒鎿嶄綔", "瀹℃牳鎿嶄綔"))) {
             return StringUtils.hasText(approveId)
-                    ? approveTodoTools.cancelReviewTodo(memoryId, approveId, extractTail(text, "鍘熷洜"))
+                    ? approveTodoTools.cancelReviewTodo(memoryId, approveId, firstNonBlank(extractTail(text, "鍘熷洜"), extractTail(text, "澶囨敞")))
                     : missingApproveId("cancel_review_action", "鍙栨秷瀹℃牳闇�瑕佹彁渚涙祦绋嬬紪鍙枫��");
         }
-        if (containsAny(text, "鍒犻櫎")) {
+        if (containsAny(text, "鍒犻櫎", "绉婚櫎")) {
             return StringUtils.hasText(approveId)
                     ? approveTodoTools.deleteTodo(memoryId, approveId)
                     : missingApproveId("delete_action", "鍒犻櫎瀹℃壒鍗曢渶瑕佹彁渚涙祦绋嬬紪鍙枫��");
         }
         if (containsAny(text, "椹冲洖", "鎷掔粷")) {
             return StringUtils.hasText(approveId)
-                    ? approveTodoTools.reviewTodo(memoryId, approveId, "reject", extractTail(text, "鍘熷洜"))
+                    ? approveTodoTools.reviewTodo(memoryId, approveId, "reject", firstNonBlank(extractTail(text, "鍘熷洜"), extractTail(text, "澶囨敞")))
                     : missingApproveId("review_action", "椹冲洖瀹℃壒闇�瑕佹彁渚涙祦绋嬬紪鍙枫��");
         }
         if (containsAny(text, "瀹℃牳閫氳繃", "瀹℃壒閫氳繃", "閫氳繃瀹℃壒", "鍚屾剰瀹℃壒", "瀹℃壒鍚屾剰")) {
@@ -76,7 +80,7 @@
                 && !containsAny(text, "鏈�氳繃", "閫氳繃鐜�", "瀹℃壒閫氳繃鐜�", "瀹℃牳閫氳繃鐜�")) {
             return approveTodoTools.reviewTodo(memoryId, approveId, "approve", extractTail(text, "澶囨敞"));
         }
-        if (containsAny(text, "淇敼")) {
+        if (containsAny(text, "淇敼", "鏇存柊", "鍙樻洿")) {
             return StringUtils.hasText(approveId)
                     ? approveTodoTools.updateTodo(
                     memoryId,
@@ -90,15 +94,30 @@
                     extractValue(text, "澶囨敞"))
                     : missingApproveId("update_action", "淇敼瀹℃壒鍗曢渶瑕佹彁渚涙祦绋嬬紪鍙枫��");
         }
-        if (containsAny(text, "鍒楄〃", "寰呭姙", "鏌ヨ瀹℃壒")) {
+        if (containsAny(text, "鍒楄〃", "寰呭姙", "鏌ヨ瀹℃壒", "鍗曟嵁", "娴佺▼", "瀹℃壒鎵�")) {
             return approveTodoTools.listTodos(
                     memoryId,
                     extractStatus(text),
                     extractApproveType(text),
                     extractKeyword(text),
-                    extractLimit(text));
+                    extractLimit(text),
+                    extractScope(text));
         }
         return null;
+    }
+
+    private boolean isStatsIntent(String text) {
+        if (containsAny(text, "缁熻", "鍒嗘瀽", "鍥捐〃", "瓒嬪娍", "鍗犳瘮", "姹囨��", "鎬婚噺", "鍒嗗竷", "鍚勬湁澶氬皯", "鏈夊灏�")) {
+            return true;
+        }
+        boolean hasQueryWord = containsAny(text, "鏌ヨ", "鏌ョ湅", "鐪嬩笅", "鐪嬬湅", "鑾峰彇");
+        boolean hasDataWord = containsAny(text, "鏁版嵁", "鎶ヨ〃", "鎯呭喌", "鏁伴噺", "閲戦");
+        boolean hasTimeWord = containsAny(text, "浠婂ぉ", "鏄ㄦ棩", "鏄ㄥぉ", "鏈懆", "涓婂懆", "鏈湀", "涓婃湀", "鏈勾", "浠婂勾", "鍘诲勾")
+                || DATE_PATTERN.matcher(text).find()
+                || RECENT_RANGE_PATTERN.matcher(text).find()
+                || HALF_RANGE_PATTERN.matcher(text).find()
+                || EXPLICIT_RANGE_PATTERN.matcher(text).matches();
+        return hasQueryWord && hasDataWord && hasTimeWord;
     }
 
     private boolean containsAny(String text, String... keywords) {
@@ -124,13 +143,13 @@
         if (containsAny(text, "寰呭鏍�", "寰呭鎵�")) {
             return "pending";
         }
-        if (containsAny(text, "瀹℃牳涓�")) {
+        if (containsAny(text, "瀹℃牳涓�", "澶勭悊涓�", "澶勭悊涓殑", "鍔炵悊涓�")) {
             return "processing";
         }
-        if (containsAny(text, "宸查�氳繃", "瀹℃牳瀹屾垚")) {
+        if (containsAny(text, "宸查�氳繃", "閫氳繃", "瀹℃牳瀹屾垚", "瀹℃壒瀹屾垚")) {
             return "approved";
         }
-        if (containsAny(text, "鏈�氳繃", "椹冲洖")) {
+        if (containsAny(text, "鏈�氳繃", "椹冲洖", "宸查┏鍥�", "鎷掔粷")) {
             return "rejected";
         }
         if (containsAny(text, "閲嶆柊鎻愪氦")) {
@@ -170,7 +189,11 @@
     private String extractKeyword(String text) {
         String cleaned = text
                 .replace("鏌ヨ", "")
+                .replace("鏌ョ湅", "")
+                .replace("鍒楀嚭", "")
+                .replace("甯垜", "")
                 .replace("瀹℃壒", "")
+                .replace("鍗曟嵁", "")
                 .replace("寰呭姙", "")
                 .replace("鍒楄〃", "")
                 .replace("鍓�10鏉�", "")
@@ -180,7 +203,7 @@
     }
 
     private String extractValue(String text, String fieldName) {
-        Pattern pattern = Pattern.compile(fieldName + "(鏀逛负|淇敼涓簗鏄�)?[:锛歖?[\\s]*([^,锛屻�傦紱;\\s]+)");
+        Pattern pattern = Pattern.compile(fieldName + "(鏀逛负|淇敼涓簗鏄�)[:锛歖?[\\s]*([^,锛屻�傦紱;\\s]+)");
         Matcher matcher = pattern.matcher(text);
         return matcher.find() ? matcher.group(2) : null;
     }
@@ -211,13 +234,13 @@
         if (containsAny(text, "浠婂ぉ", "鏄ㄦ棩", "鏄ㄥぉ", "鏈懆", "涓婂懆", "鏈湀", "涓婃湀", "鏈勾", "浠婂勾", "鍘诲勾")) {
             return text;
         }
-        if (Pattern.compile("杩慭\d+(澶﹟鍛▅涓湀|鏈坾骞�)").matcher(text).find()) {
+        if (RECENT_RANGE_PATTERN.matcher(text).find()) {
             return text;
         }
-        if (Pattern.compile("鏈�杩慭\d+(澶﹟鍛▅涓湀|鏈坾骞�)").matcher(text).find()) {
+        if (HALF_RANGE_PATTERN.matcher(text).find()) {
             return text;
         }
-        if (text.contains("鍒�") || text.contains("鑷�")) {
+        if (EXPLICIT_RANGE_PATTERN.matcher(text).matches()) {
             return text;
         }
         return null;
@@ -227,7 +250,7 @@
         if (!text.contains(fieldName)) {
             return null;
         }
-        Matcher matcher = Pattern.compile(fieldName + "(鏀逛负|淇敼涓簗鏄�)?[:锛歖?[\\s]*(\\d{1,2})").matcher(text);
+        Matcher matcher = Pattern.compile(fieldName + "(鏀逛负|淇敼涓簗鏄�)[:锛歖?[\\s]*(\\d{1,2})").matcher(text);
         return matcher.find() ? Integer.parseInt(matcher.group(2)) : null;
     }
 
@@ -246,6 +269,20 @@
         return matcher.find() ? matcher.group(2).trim() : null;
     }
 
+    private String extractScope(String text) {
+        if (containsAny(text, "鎴戝彂璧�", "鎴戞彁浜�", "鎴戠敵璇�", "鐢宠浜烘槸鎴�")) {
+            return "applicant";
+        }
+        if (containsAny(text, "寰呮垜瀹℃壒", "寰呮垜瀹℃牳", "鎴戝鐞�", "鎴戝鎵�", "褰撳墠寰呮垜", "闇�瑕佹垜澶勭悊")) {
+            return "approver";
+        }
+        return "related";
+    }
+
+    private String firstNonBlank(String first, String second) {
+        return StringUtils.hasText(first) ? first : second;
+    }
+
     private String missingApproveId(String type, String description) {
         Map<String, Object> result = new LinkedHashMap<>();
         result.put("success", false);

--
Gitblit v1.9.3