huminmin
16 小时以前 271f4a25576ac6c2c8f2c4eb4c9782d6eef85124
src/main/java/com/ruoyi/ai/assistant/ApproveTodoIntentExecutor.java
@@ -16,6 +16,11 @@
    private static final Pattern APPROVE_ID_PATTERN = Pattern.compile("\\b[A-Za-z]*\\d{8,}\\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 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;
@@ -23,7 +28,7 @@
        this.approveTodoTools = approveTodoTools;
    }
    public String tryExecute(String message) {
    public String tryExecute(String memoryId, String message) {
        if (!StringUtils.hasText(message)) {
            return null;
        }
@@ -31,47 +36,54 @@
        String text = message.trim();
        String approveId = extractApproveId(text);
        if (containsAny(text, "统计", "分析", "图表", "趋势", "占比")) {
            return approveTodoTools.getTodoStats();
        if (isStatsIntent(text)) {
            return approveTodoTools.getTodoStats(
                    memoryId,
                    extractStartDate(text),
                    extractEndDate(text),
                    extractTimeRange(text)
            );
        }
        if (containsAny(text, "流转", "进度", "节点", "日志")) {
        if (containsAny(text, "流转", "进度", "节点", "日志", "卡在", "卡到", "当前审批人", "处理记录")) {
            return StringUtils.hasText(approveId)
                    ? approveTodoTools.getTodoProgress(approveId)
                    ? approveTodoTools.getTodoProgress(memoryId, approveId)
                    : missingApproveId("todo_progress", "查询审批进度需要提供流程编号。");
        }
        if (containsAny(text, "详情", "明细") && !containsAny(text, "列表")) {
            return StringUtils.hasText(approveId)
                    ? approveTodoTools.getTodoDetail(approveId)
                    ? approveTodoTools.getTodoDetail(memoryId, approveId)
                    : missingApproveId("todo_detail", "查询审批详情需要提供流程编号。");
        }
        if (containsAny(text, "取消审核", "撤销审核", "回退审核")) {
        if (containsAny(text, "取消审核", "撤销审核", "回退审核", "撤销审批", "撤回审批")
                || (containsAny(text, "撤销", "撤回") && containsAny(text, "审批操作", "审核操作"))) {
            return StringUtils.hasText(approveId)
                    ? approveTodoTools.cancelReviewTodo(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(approveId)
                    ? approveTodoTools.deleteTodo(memoryId, approveId)
                    : missingApproveId("delete_action", "删除审批单需要提供流程编号。");
        }
        if (containsAny(text, "驳回", "拒绝")) {
            return StringUtils.hasText(approveId)
                    ? approveTodoTools.reviewTodo(approveId, "reject", extractTail(text, "原因"))
                    ? approveTodoTools.reviewTodo(memoryId, approveId, "reject", firstNonBlank(extractTail(text, "原因"), extractTail(text, "备注")))
                    : missingApproveId("review_action", "驳回审批需要提供流程编号。");
        }
        if (containsAny(text, "审核通过", "审批通过", "通过审批", "同意审批", "审批同意")) {
            return StringUtils.hasText(approveId)
                    ? approveTodoTools.reviewTodo(approveId, "approve", extractTail(text, "备注"))
                    ? approveTodoTools.reviewTodo(memoryId, approveId, "approve", extractTail(text, "备注"))
                    : missingApproveId("review_action", "审批通过需要提供流程编号。");
        }
        if (StringUtils.hasText(approveId)
                && containsAny(text, "通过", "同意")
                && !containsAny(text, "未通过", "通过率", "审批通过率", "审核通过率")) {
            return approveTodoTools.reviewTodo(approveId, "approve", extractTail(text, "备注"));
            return approveTodoTools.reviewTodo(memoryId, approveId, "approve", extractTail(text, "备注"));
        }
        if (containsAny(text, "修改")) {
        if (containsAny(text, "修改", "更新", "变更")) {
            return StringUtils.hasText(approveId)
                    ? approveTodoTools.updateTodo(
                    memoryId,
                    approveId,
                    extractValue(text, "标题"),
                    extractDateValue(text, "开始日期"),
@@ -82,14 +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) {
@@ -115,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, "重新提交")) {
@@ -161,40 +189,100 @@
    private String extractKeyword(String text) {
        String cleaned = text
                .replace("查询", "")
                .replace("查看", "")
                .replace("列出", "")
                .replace("帮我", "")
                .replace("审批", "")
                .replace("单据", "")
                .replace("待办", "")
                .replace("列表", "")
                .replace("前10条", "")
                .replace("前20条", "")
                .replace("最近10条", "")
                .trim();
        return cleaned.length() >= 2 ? cleaned : null;
    }
    private String extractValue(String text, String fieldName) {
        Matcher matcher = Pattern.compile(fieldName + "(改为|修改为|为|是)([^,。,;;\\s]+)").matcher(text);
        Pattern pattern = Pattern.compile(fieldName + "(改为|修改为|是)[::]?[\\s]*([^,,。;;\\s]+)");
        Matcher matcher = pattern.matcher(text);
        return matcher.find() ? matcher.group(2) : null;
    }
    private String extractDateValue(String text, String fieldName) {
        Matcher matcher = Pattern.compile(fieldName + "(改为|修改为|为|是)(\\d{4}-\\d{2}-\\d{2})").matcher(text);
        return matcher.find() ? matcher.group(2) : null;
        int index = text.indexOf(fieldName);
        if (index < 0) {
            return null;
        }
        Matcher matcher = DATE_PATTERN.matcher(text.substring(index));
        return matcher.find() ? matcher.group(1) : null;
    }
    private String extractStartDate(String text) {
        Matcher matcher = DATE_PATTERN.matcher(text);
        return matcher.find() ? matcher.group(1) : null;
    }
    private String extractEndDate(String text) {
        Matcher matcher = DATE_PATTERN.matcher(text);
        if (!matcher.find()) {
            return null;
        }
        return matcher.find() ? matcher.group(1) : null;
    }
    private String extractTimeRange(String text) {
        if (containsAny(text, "今天", "昨日", "昨天", "本周", "上周", "本月", "上月", "本年", "今年", "去年")) {
            return text;
        }
        if (RECENT_RANGE_PATTERN.matcher(text).find()) {
            return text;
        }
        if (HALF_RANGE_PATTERN.matcher(text).find()) {
            return text;
        }
        if (EXPLICIT_RANGE_PATTERN.matcher(text).matches()) {
            return text;
        }
        return null;
    }
    private Integer extractIntegerValue(String text, String fieldName) {
        Matcher matcher = Pattern.compile(fieldName + "(改为|修改为|为|是)(\\d{1,2})").matcher(text);
        if (!text.contains(fieldName)) {
            return null;
        }
        Matcher matcher = Pattern.compile(fieldName + "(改为|修改为|是)[::]?[\\s]*(\\d{1,2})").matcher(text);
        return matcher.find() ? Integer.parseInt(matcher.group(2)) : null;
    }
    private BigDecimal extractBigDecimalValue(String text, String fieldName) {
        Matcher matcher = Pattern.compile(fieldName + "(改为|修改为|为|是)(\\d+(\\.\\d+)?)").matcher(text);
        return matcher.find() ? new BigDecimal(matcher.group(2)) : null;
        int index = text.indexOf(fieldName);
        if (index < 0) {
            return null;
        }
        Matcher matcher = NUMBER_PATTERN.matcher(text.substring(index));
        return matcher.find() ? new BigDecimal(matcher.group(1)) : null;
    }
    private String extractTail(String text, String key) {
        Matcher matcher = Pattern.compile(key + "(是|为|:|:)?(.+)").matcher(text);
        Pattern pattern = Pattern.compile(key + "(是|为)?[::]?[\\s]*(.+)");
        Matcher matcher = pattern.matcher(text);
        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);