From 05c82d89b6df8c236feb0e4dc3f83f18e8414df0 Mon Sep 17 00:00:00 2001
From: 陈昶聿 <chychen@nbjetron.com>
Date: 星期一, 22 六月 2026 16:14:55 +0800
Subject: [PATCH] 【市一】大模型

---
 smartor/src/main/java/com/smartor/common/QwenLLMUtil.java                                |  214 +++++++++++++++++++++++++++++++++++
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java                             |   85 +++++++++++++
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/ServiceSubtaskController.java |   10 +
 smartor/src/main/resources/mapper/smartor/ServiceSubtaskMapper.xml                       |   12 ++
 4 files changed, 317 insertions(+), 4 deletions(-)

diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/ServiceSubtaskController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/ServiceSubtaskController.java
index 0f3c6be..3b588b5 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/ServiceSubtaskController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/ServiceSubtaskController.java
@@ -883,6 +883,16 @@
         ryTask.dealOutHospInfo();
     }
 
+    @PostMapping("/compensateTasktest")
+    public void compensateTasktest(@RequestParam("subId")Long subId) {
+        ryTask.compensateTaskTest(subId);
+    }
+
+    @PostMapping("/longTaskSendtest")
+    public void longTaskSendtest(@RequestParam("subId")Long subId) {
+        ryTask.longTaskSendTest(subId);
+    }
+
     @PostMapping("/syncMedInhospForShiyi")
     public void syncMedInhospForShiyi(@RequestParam("startTime") String startTime, @RequestParam("endTime") String endTime) {
         collectHISService.syncMedInhosp(startTime, endTime);
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
index d952720..79c36ea 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
@@ -685,6 +685,86 @@
     }
 
     /**
+     * 闀挎湡浠诲姟鍙戦��
+     */
+    public void longTaskSendTest(Long subId) {
+        //鑾峰彇浠诲姟淇℃伅
+        ServiceTask st = new ServiceTask();
+        st.setDelFlag("0");
+        st.setLongTask(1);
+        List<ServiceTask> serviceTasks = serviceTaskMapper.selectServiceTaskList(st);
+        log.info("銆恖ongTaskSend銆戣幏鍙栧埌{}涓暱鏈熶换鍔�", serviceTasks.size());
+        for (ServiceTask serviceTask : serviceTasks) {
+            CommonTaskcallMQ commonTaskcallMQ = new CommonTaskcallMQ();
+            commonTaskcallMQ.setTaskid(serviceTask.getTaskid());
+            commonTaskcallMQ.setPreachform(serviceTask.getPreachform());
+            commonTaskcallMQ.setSendType("2");
+
+            //閫氳繃浠诲姟ID鎷垮埌鎮h�呬俊鎭�,骞朵笖闅忚鏃堕棿寰楁槸浠婂ぉ涔嬪墠鐨�
+            ServiceSubtaskEntity serviceSubtaskVO = new ServiceSubtaskEntity();
+            serviceSubtaskVO.setTaskid(commonTaskcallMQ.getTaskid());
+            serviceSubtaskVO.setSendstate(2L);
+            serviceSubtaskVO.setIsVisitAgain(1);
+            serviceSubtaskVO.setSubId(subId);
+            serviceSubtaskVO.setVisitTime(new Date());
+            List<ServiceSubtask> selectServiceSubtaskList = serviceSubtaskMapper.queryServiceSubtaskList(serviceSubtaskVO);
+            for (ServiceSubtask serviceSubtask : selectServiceSubtaskList) {
+                sfHandlle(serviceSubtask);
+            }
+        }
+    }
+
+    /**
+     * 澶勭悊琛ュ伩浠诲姟
+     */
+    public void compensateTaskTest(Long subId) {
+        //鑾峰彇鍒皊endstate=3 骞朵笖 visit_time涓哄皬浜庣瓑浜庝粖澶╃殑subtask
+        ServiceSubtaskEntity serviceSubtaskVO = new ServiceSubtaskEntity();
+        serviceSubtaskVO.setSendstate(3L);
+        serviceSubtaskVO.setSubId(subId);
+        serviceSubtaskVO.setVisitTime(new Date());
+        List<ServiceSubtask> serviceSubtaskList = serviceSubtaskMapper.getCompensateServiceSubtaskList(serviceSubtaskVO);
+        for (ServiceSubtask serviceSubtask : serviceSubtaskList) {
+            //鏍规嵁褰撳墠鐨勬墽琛屾柟寮忥紝鑾峰彇涓嬩竴绉嶆墽琛屾柟寮�
+            ServiceSubtaskPreachform serviceSubtaskPreachform = new ServiceSubtaskPreachform();
+            serviceSubtaskPreachform.setTaskid(serviceSubtask.getTaskid());
+            serviceSubtaskPreachform.setSubid(serviceSubtask.getId());
+            serviceSubtaskPreachform.setOrgid(serviceSubtask.getOrgid());
+            List<ServiceSubtaskPreachform> serviceSubtaskPreachforms = serviceSubtaskPreachformMapper.selectServiceSubtaskPreachformList(serviceSubtaskPreachform);
+            //鑾峰彇褰撳墠鎵ц鏂瑰紡鐨勫簭鍙�
+            Optional<Long> currentSort = serviceSubtaskPreachforms.stream().filter(item -> serviceSubtask.getCurrentPreachform().equals(item.getPreachform())).map(ServiceSubtaskPreachform::getSort).findFirst();
+            Optional<Long> id = serviceSubtaskPreachforms.stream().filter(item -> serviceSubtask.getCurrentPreachform().equals(item.getPreachform())).map(ServiceSubtaskPreachform::getId).findFirst();
+            if (currentSort.isPresent()) {
+                //1鍏堟鏌ヤ竴涓嬶紝鏄笉鏄湁鎵ц鐘舵�佹槸瀹屾垚鐨勶紙鎬曚箣鍓嶅凡缁忔湁瀹岀殑浜嗭紝娌℃湁灏唖ervuce_subtask鐨勭姸鎬佹敼鎴愬姛锛岃繖閲屽啀妫�鏌ヤ竴涓嬶級
+                boolean finishState = serviceSubtaskPreachforms.stream().allMatch(item -> item.getSendstate().equals("9"));
+                if (finishState) {
+                    serviceSubtask.setSendstate(6L);
+                    serviceSubtaskMapper.updateServiceSubtask(serviceSubtask);
+                    continue;
+                }
+
+                //2鍒ゆ柇涓�涓嬶紝褰撳墠鐨剆ort鏄笉鏄瓑浜庨渶瑕佹墽琛岀殑鎬讳釜鏁帮紝濡傛灉绛変簬鐨勮瘽锛岃鏄庢槸鏈�鍚庝竴涓紝鐩存帴灏唖ervuce_subtask鐨勭姸鎬佹敼鎴�5锛屾墽琛屽け璐ュ氨琛屼簡
+                Long cs = currentSort.get();
+                if (cs.equals(serviceSubtaskPreachforms.size())) {
+                    serviceSubtask.setSendstate(7L);
+                    serviceSubtask.setRemark("澶勭悊琛ュ伩浠诲姟,褰撳墠澶勭悊鏈�鍚庤ˉ鍋匡紝鍏ㄩ儴鎵ц澶辫触锛堣秴鏃讹級");
+
+                    serviceSubtaskMapper.updateServiceSubtask(serviceSubtask);
+                    //淇敼鍙戦�佹柟寮忕殑鐘舵�佷负澶辫触
+                    serviceSubtaskPreachform.setSendstate("5");
+                    serviceSubtaskPreachform.setId(id.get());
+
+                    serviceSubtaskPreachformMapper.updateServiceSubtaskPreachform(serviceSubtaskPreachform);
+                    continue;
+                }
+
+                //3.涓嶆槸鏈�鍚庝竴涓紝鑾峰彇鍒颁笅涓�涓墽琛屾柟寮�(鍥犱负閮芥槸鍦ㄤ粖澶╂墽琛岋紝閭e氨鐩存帴鍙戝嚭鍘诲氨瀹屼簡)
+                sfHandlle(serviceSubtask);
+            }
+        }
+    }
+
+    /**
      * 璁剧疆澶辫触浠诲姟榛樿鍊�,骞跺皢澶辫触浠诲姟閲嶆柊缃负鎴愬姛
      * <p>
      * *@param failDay   (澶辫触澶╂暟锛氳窛绂诲綋鍓嶆棩鏈熷け璐ュぉ鏁�)
@@ -971,6 +1051,7 @@
                     //浠诲姟鍙戦�佽褰�
                     ServiceSubtaskRecord serviceSubtaskRecord = new ServiceSubtaskRecord();
                     serviceSubtaskRecord.setTaskid(serviceSubtask.getTaskid().toString());
+                    serviceSubtaskRecord.setSubtaskId(serviceSubtask.getId());
                     serviceSubtaskRecord.setUuid(UUID.randomUUID().toString());
                     serviceSubtaskRecord.setTasktype(serviceSubtask.getType());
                     serviceSubtaskRecord.setPreachform("4");
@@ -1028,8 +1109,6 @@
                     if (active.equals("hzszlyy")) {
                         //澶勭悊涓枃涔辩爜闂
                         wxCode = smsUtils.sendChat(url, patArchive.getTelcode(), serviceSubtask.getSfzh());
-                        log.info(wxCode);
-
                     } else {
                         wxCode = getWXCode(serviceSubtask.getSfzh(), url, serviceSubtask.getTaskName(), serviceSubtask.getTaskDesc(), patArchive.getTelcode(), serviceSubtask.getSendname(), patArchive.getPatidHis(), wxqqxx);
                     }
@@ -1346,9 +1425,7 @@
                     //serviceSubtask.setRemark("setSuccessPreachForm鏂规硶锛屽綋鍓嶇殑preachform宸茬粡鏄渶鍚庝竴涓簡锛屽叏閮ㄦ墽琛屽け璐�");
                     serviceSubtaskMapper.updateServiceSubtask(serviceSubtask);
                     return true;
-
                 }
-
             }
         } else {
             log.error("銆愬畾鏃朵换鍔′腑璇ユ偅鑰呮病鏈夋煡璇㈠埌灞炰簬浠栫殑鍙戦�佹柟寮忥紝subid锛歿},prechform:{},orgid:{}銆�", serviceSubtask.getId(), preachform, serviceSubtask.getOrgid());
diff --git a/smartor/src/main/java/com/smartor/common/QwenLLMUtil.java b/smartor/src/main/java/com/smartor/common/QwenLLMUtil.java
new file mode 100644
index 0000000..f810081
--- /dev/null
+++ b/smartor/src/main/java/com/smartor/common/QwenLLMUtil.java
@@ -0,0 +1,214 @@
+package com.smartor.common;
+
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.common.utils.http.HttpUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 閫氫箟鍗冮棶锛圦wen锛夊ぇ妯″瀷宸ュ叿绫汇��
+ * <p>
+ * 鍩轰簬闃块噷浜戠櫨鐐� DashScope 鐨� OpenAI 鍏煎鎺ュ彛锛坽@code /compatible-mode/v1/chat/completions}锛夛紝
+ * 涓昏鐢ㄤ簬璇箟鍖归厤锛氭妸璇煶璇嗗埆寰楀埌鐨勮嚜鐢辨枃鏈紝褰掍竴鍖栧埌涓�缁勯璁鹃�夐」涓渶鎺ヨ繎鐨勪竴涓��
+ * <p>
+ * 閰嶇疆椤癸紙application.yml锛夛細
+ * <pre>
+ * qwen:
+ *   api-key: sk-xxxxxxxx          # 鐧剧偧 API Key锛屽繀濉�
+ *   model: qwen-plus             # 妯″瀷鍚嶇О锛岄粯璁� qwen-plus
+ *   url: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions
+ * </pre>
+ */
+@Slf4j
+@Component
+public class QwenLLMUtil {
+
+    /** 鐧剧偧 API Key */
+    @Value("${qwen.api-key:}")
+    private String apiKey;
+
+    /** 妯″瀷鍚嶇О */
+    @Value("${qwen.model:qwen-plus}")
+    private String model;
+
+    /** 鎺ュ彛鍦板潃锛圤penAI 鍏煎妯″紡锛� */
+    @Value("${qwen.url:https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions}")
+    private String url;
+
+    /**
+     * 鍒ゆ柇璇煶鏂囨湰鏈�鎺ヨ繎鍝釜閫夐」銆�
+     *
+     * @param voiceText 璇煶璇嗗埆寰楀埌鐨勬枃鏈�
+     * @param options   鍊欓�夐�夐」鍒楄〃
+     * @return 鍛戒腑鐨勯�夐」鍘熸枃锛涙棤娉曞尮閰嶄换涓�閫夐」鏃惰繑鍥� {@code null}
+     */
+    public String matchOption(String voiceText, List<String> options) {
+        int index = matchOptionIndex(voiceText, options);
+        return index < 0 ? null : options.get(index);
+    }
+
+    /**
+     * 鍒ゆ柇璇煶鏂囨湰鏈�鎺ヨ繎鍝釜閫夐」锛岃繑鍥為�夐」鍦ㄥ垪琛ㄤ腑鐨勪笅鏍囥��
+     *
+     * @param voiceText 璇煶璇嗗埆寰楀埌鐨勬枃鏈�
+     * @param options   鍊欓�夐�夐」鍒楄〃
+     * @return 鍛戒腑閫夐」鐨勪笅鏍囷紙浠� 0 寮�濮嬶級锛涙棤娉曞尮閰嶄换涓�閫夐」鏃惰繑鍥� {@code -1}
+     */
+    public int matchOptionIndex(String voiceText, List<String> options) {
+        if (StringUtils.isBlank(voiceText) || options == null || options.isEmpty()) {
+            return -1;
+        }
+        // 鍙湁涓�涓�夐」鏃舵棤闇�璋冪敤妯″瀷
+        if (options.size() == 1) {
+            return 0;
+        }
+
+        StringBuilder optionText = new StringBuilder();
+        for (int i = 0; i < options.size(); i++) {
+            optionText.append(i + 1).append(". ").append(options.get(i)).append('\n');
+        }
+
+        String systemPrompt = "浣犳槸涓�涓涔夊尮閰嶅姪鎵嬨�傜敤鎴蜂細缁欏嚭涓�娈佃闊宠瘑鍒枃鏈拰鑻ュ共涓甫缂栧彿鐨勯�夐」锛�"
+                + "璇峰垽鏂繖娈垫枃鏈湪璇箟涓婃渶鎺ヨ繎鍝竴涓�夐」銆傚彧鍏佽浠庣粰瀹氶�夐」涓�夋嫨锛�"
+                + "涓嶈鍋氫换浣曡В閲娿�傜洿鎺ヨ緭鍑烘渶鍖归厤閫夐」鐨勭紪鍙锋暟瀛楋紱鑻ユ病鏈変换浣曢�夐」涓庢枃鏈浉鍏筹紝鍒欒緭鍑� 0銆�";
+        String userPrompt = "璇煶鏂囨湰锛�" + voiceText + "\n\n閫夐」锛歕n" + optionText
+                + "\n璇峰彧杈撳嚭涓�涓暟瀛楋紙鏈�鍖归厤閫夐」鐨勭紪鍙凤紝娌℃湁鍖归厤鍒欒緭鍑� 0锛夈��";
+
+        String content = chat(systemPrompt, userPrompt);
+        if (StringUtils.isBlank(content)) {
+            return -1;
+        }
+
+        Integer number = extractFirstNumber(content);
+        if (number == null || number <= 0 || number > options.size()) {
+            log.warn("Qwen 閫夐」鍖归厤鏈懡涓紝voiceText={}, options={}, modelReturn={}", voiceText, options, content);
+            return -1;
+        }
+        return number - 1;
+    }
+
+    /**
+     * 鍒ゆ柇璇煶鏂囨湰鏄惁绗﹀悎杩欎釜鎰忔��
+     *
+     * @param voiceText 璇煶璇嗗埆寰楀埌鐨勬枃鏈�
+     * @return 鍛戒腑鐨勯�夐」鍘熸枃锛涙棤娉曞尮閰嶄换涓�閫夐」鏃惰繑鍥� {@code null}
+     */
+    public int matchRegex(String voiceText, String value, String regexText) {
+        if (StringUtils.isBlank(voiceText) || regexText == null || regexText.isEmpty()) {
+            return -1;
+        }
+
+        String systemPrompt = "浣犳槸涓�涓涔夊尮閰嶅姪鎵嬨�傜敤鎴蜂細缁欏嚭涓�娈佃闊宠瘑鍒枃鏈�佹鍒欏尮閰嶆枃鏈�佸搴旀寚鏍囧��"
+                + "璇峰垽鏂繖娈垫枃鏈槸鍚︽帴杩戞鍒欏尮閰嶈鍒欐垨鑰呭搴旀寚鏍囧�肩殑鎰忔��"
+                + "涓嶈鍋氫换浣曡В閲娿�傝嫢鏈夌浉鍏虫剰鎬濓紝鑳藉尮閰嶇殑涓婏紝鐩存帴杈撳嚭 1锛涜嫢涓庢枃鏈剰鎬濆畬鍏ㄤ笉鐩稿叧锛屽垯杈撳嚭 0銆�";
+        String userPrompt = "璇煶鏂囨湰锛�" + voiceText + "\n\n姝e垯鍖归厤鏂囨湰锛歕n" + regexText
+                +  "\n\n瀵瑰簲鎸囨爣鍊硷細\n" + value
+                + "\n璇峰彧杈撳嚭涓�涓暟瀛楋紙鍖归厤杈撳嚭 1锛屾病鏈夊尮閰嶅垯杈撳嚭 0锛夈��";
+
+        String content = chat(systemPrompt, userPrompt);
+        if (StringUtils.isBlank(content)) {
+            return -1;
+        }
+
+        Integer number = extractFirstNumber(content);
+        if (number == null || number <= 0) {
+            log.warn("Qwen 閫夐」鍖归厤鏈懡涓紝voiceText={}, regexText={}, modelReturn={}", voiceText, regexText, content);
+            return -1;
+        }
+        return number - 1;
+    }
+
+    /**
+     * 閫氱敤瀵硅瘽璋冪敤锛岃繑鍥炴ā鍨嬪洖澶嶇殑鏂囨湰鍐呭銆�
+     *
+     * @param systemPrompt 绯荤粺鎻愮ず璇嶏紝鍙负绌�
+     * @param userPrompt   鐢ㄦ埛鎻愮ず璇�
+     * @return 妯″瀷鍥炲姝f枃锛涜皟鐢ㄥけ璐ヨ繑鍥� {@code null}
+     */
+    public String chat(String systemPrompt, String userPrompt) {
+        if (StringUtils.isBlank(apiKey)) {
+            throw new IllegalStateException("閫氫箟鍗冮棶 API Key 鏈厤缃紙qwen.api-key锛�");
+        }
+        if (StringUtils.isBlank(userPrompt)) {
+            throw new IllegalArgumentException("userPrompt 涓嶈兘涓虹┖");
+        }
+
+        JSONArray messages = new JSONArray();
+        if (StringUtils.isNotBlank(systemPrompt)) {
+            messages.add(message("system", systemPrompt));
+        }
+        messages.add(message("user", userPrompt));
+
+        JSONObject body = new JSONObject();
+        body.put("model", model);
+        body.put("messages", messages);
+        // 鍖归厤鍦烘櫙闇�瑕佺ǔ瀹氱粨鏋滐紝娓╁害璋冧綆
+        body.put("temperature", 0.01);
+
+        Map<String, String> headers = new HashMap<>();
+        headers.put("Authorization", "Bearer " + apiKey);
+        headers.put("Content-Type", "application/json");
+
+        String response = HttpUtils.sendPostByHeader(url, body.toJSONString(), headers);
+        if (StringUtils.isBlank(response)) {
+            log.error("閫氫箟鍗冮棶杩斿洖涓虹┖锛寀rl={}, body={}", url, body.toJSONString());
+            return null;
+        }
+
+        try {
+            JSONObject json = JSONObject.parseObject(response);
+            JSONArray choices = json.getJSONArray("choices");
+            if (choices == null || choices.isEmpty()) {
+                log.error("閫氫箟鍗冮棶鍝嶅簲鏃� choices锛宺esponse={}", response);
+                return null;
+            }
+            JSONObject msg = choices.getJSONObject(0).getJSONObject("message");
+            return msg == null ? null : StringUtils.trim(msg.getString("content"));
+        } catch (Exception e) {
+            log.error("瑙f瀽閫氫箟鍗冮棶鍝嶅簲澶辫触锛宺esponse={}", response, e);
+            return null;
+        }
+    }
+
+    private JSONObject message(String role, String content) {
+        JSONObject msg = new JSONObject();
+        msg.put("role", role);
+        msg.put("content", content);
+        return msg;
+    }
+
+    /**
+     * 浠庢ā鍨嬪洖澶嶄腑鎻愬彇绗竴涓暣鏁般�傛ā鍨嬪伓灏斾細鍥炲 鈥滈�夐」2鈥� 鈥�2銆傗�� 涔嬬被锛屽仛涓�娆″厹搴曡В鏋愩��
+     */
+    private Integer extractFirstNumber(String text) {
+        List<Character> digits = new ArrayList<>();
+        for (int i = 0; i < text.length(); i++) {
+            char c = text.charAt(i);
+            if (c >= '0' && c <= '9') {
+                digits.add(c);
+            } else if (!digits.isEmpty()) {
+                break;
+            }
+        }
+        if (digits.isEmpty()) {
+            return null;
+        }
+        StringBuilder sb = new StringBuilder();
+        for (char c : digits) {
+            sb.append(c);
+        }
+        try {
+            return Integer.parseInt(sb.toString());
+        } catch (NumberFormatException e) {
+            return null;
+        }
+    }
+}
diff --git a/smartor/src/main/resources/mapper/smartor/ServiceSubtaskMapper.xml b/smartor/src/main/resources/mapper/smartor/ServiceSubtaskMapper.xml
index dd46e0d..e217248 100644
--- a/smartor/src/main/resources/mapper/smartor/ServiceSubtaskMapper.xml
+++ b/smartor/src/main/resources/mapper/smartor/ServiceSubtaskMapper.xml
@@ -275,6 +275,9 @@
         <if test="orgid != null and orgid != ''">
             and orgid = #{orgid}
         </if>
+        <if test="subId != null">
+            AND id = #{subId}
+        </if>
         <if test="taskid != null ">and taskid = #{taskid}</if>
         <if test="visitTime != null">
             AND date_format(visit_time,'%y%m%d') &lt;= date_format(#{visitTime},'%y%m%d')
@@ -291,6 +294,9 @@
         and sendstate = 5
         <if test="orgid != null and orgid != ''">
             and orgid = #{orgid}
+        </if>
+        <if test="subId != null">
+            AND id = #{subId}
         </if>
         <if test="taskid != null ">and taskid = #{taskid}</if>
         <if test="visitTime != null">
@@ -570,6 +576,9 @@
         <if test="visitTime != null">
             AND date_format(visit_time,'%y%m%d') &lt;= date_format(#{visitTime},'%y%m%d')
         </if>
+        <if test="subId != null">
+            AND id = #{subId}
+        </if>
         <if test="sendstate != null ">and sendstate = #{sendstate}</if>
         <if test="continueFlag != null ">and continue_flag = #{continueFlag}</if>
         <if test="continueTimeNow != null ">and continue_time_now = #{continueTimeNow,jdbcType=TIMESTAMP}</if>
@@ -585,6 +594,9 @@
         <if test="visitTime != null">
             AND date_format(visit_time,'%y%m%d') &lt;= date_format(DATE_ADD(#{visitTime}, INTERVAL 1 DAY),'%y%m%d')
         </if>
+        <if test="subId != null">
+            AND id = #{subId}
+        </if>
         <if test="sendstate != null ">and sendstate = #{sendstate}</if>
         <if test="continueFlag != null ">and continue_flag = #{continueFlag}</if>
         <if test="continueTimeNow != null ">and continue_time_now = #{continueTimeNow,jdbcType=TIMESTAMP}</if>

--
Gitblit v1.9.3