From 40a8157440e3b906da8f52e07d939d78c3f4c313 Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期日, 12 四月 2026 16:14:06 +0800
Subject: [PATCH] feat: 任务增加统计、同步增加通知

---
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/HospDataController.java |  279 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 279 insertions(+), 0 deletions(-)

diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/HospDataController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/HospDataController.java
index d4f92b1..5904fca 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/HospDataController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/HospDataController.java
@@ -2,16 +2,27 @@
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.HospitalTokenizerUtil;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.system.domain.HospData;
+import com.ruoyi.system.domain.HospitalTokenizerTask;
+import com.ruoyi.system.domain.TbHospData;
 import com.ruoyi.system.mapper.HospDataMapper;
+import com.ruoyi.system.service.HospitalTokenizerAsyncService;
 import com.ruoyi.system.service.ISQLHospDataService;
+import com.ruoyi.system.service.ITbHospDataService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
+import java.util.UUID;
 
 /**
  * 鍖婚櫌鏁版嵁Controller
@@ -25,11 +36,25 @@
 @RequestMapping("/system/hospital")
 public class HospDataController extends BaseController {
     
+    /**
+     * 鍖婚櫌鎼滅储鏈�浣庡尮閰嶅垎鏁伴槇鍊硷紙浣庝簬姝ゅ垎鏁扮殑缁撴灉灏嗚杩囨护锛�
+     */
+    private static final int MIN_MATCH_SCORE_THRESHOLD = 1;
+    
     @Autowired
     private HospDataMapper hospDataMapper;
 
     @Autowired
     private ISQLHospDataService sqlHospDataService;
+    
+    @Autowired
+    private ITbHospDataService tbHospDataService;
+    
+    @Autowired
+    private com.ruoyi.system.mapper.TbHospDataMapper tbHospDataMapper;
+    
+    @Autowired
+    private HospitalTokenizerAsyncService asyncService;
     
     /**
      * 鎼滅储鍖婚櫌锛堜粠MySQL tb_hosp_data琛ㄦ煡璇級
@@ -181,4 +206,258 @@
         
         return success(hospitals);
     }
+    
+    /**
+     * 鎵归噺鐢熸垚鎵�鏈夊尰闄㈢殑鍒嗚瘝锛堝紓姝ワ級
+     * 绠$悊鍛樻帴鍙o紝鐢ㄤ簬鍒濆鍖栨垨閲嶆柊鐢熸垚鍖婚櫌鍒嗚瘝
+     * 
+     * @return 浠诲姟ID
+     */
+    @GetMapping("/generateKeywords")
+    public AjaxResult generateAllHospitalKeywords() {
+        logger.info("寮�濮嬫壒閲忕敓鎴愬尰闄㈠垎璇嶏紙寮傛锛�...");
+        
+        try {
+            // 鐢熸垚浠诲姟ID
+            String taskId = UUID.randomUUID().toString().replace("-", "");
+            
+            // 寮傛鎵ц浠诲姟
+            asyncService.executeTokenizerTask(taskId);
+            
+            logger.info("鍖婚櫌鍒嗚瘝浠诲姟宸插惎鍔�: taskId={}", taskId);
+            
+            // 绔嬪嵆杩斿洖浠诲姟ID
+            return success()
+                .put("taskId", taskId)
+                .put("message", "鍒嗚瘝浠诲姟宸插惎鍔紝璇锋煡璇换鍔¤繘搴�");
+            
+        } catch (Exception e) {
+            logger.error("鍚姩鍖婚櫌鍒嗚瘝浠诲姟澶辫触", e);
+            return error("鍚姩澶辫触锛�" + e.getMessage());
+        }
+    }
+    
+    /**
+     * 鏌ヨ鍖婚櫌鍒嗚瘝浠诲姟杩涘害
+     * 
+     * @param taskId 浠诲姟ID
+     * @return 浠诲姟杩涘害淇℃伅
+     */
+    @GetMapping("/getTaskProgress")
+    public AjaxResult getTaskProgress(@RequestParam("taskId") String taskId) {
+        try {
+            HospitalTokenizerTask task = asyncService.getTaskStatus(taskId);
+            
+            if (task == null) {
+                return error("浠诲姟涓嶅瓨鍦ㄦ垨宸茶繃鏈�");
+            }
+            
+            return success(task);
+            
+        } catch (Exception e) {
+            logger.error("鏌ヨ浠诲姟杩涘害澶辫触: taskId={}", taskId, e);
+            return error("鏌ヨ澶辫触锛�" + e.getMessage());
+        }
+    }
+    
+    /**
+     * 鍩轰簬鍒嗚瘝鍖归厤鎼滅储鍖婚櫌
+     * 鍓嶇浼犲叆鍖婚櫌淇℃伅锛岃繘琛屽垎璇嶅悗涓庢暟鎹簱涓殑鍒嗚瘝鍖归厤
+     * 鏍规嵁鍖归厤鐨勫垎璇嶆暟閲忚繘琛屾潈閲嶆帓搴忥紝鍖归厤瓒婂鎺掑悕瓒婇潬鍓�
+     * 
+     * @param searchText 鎼滅储鏂囨湰锛堝尰闄㈠悕绉般�佸湴鍧�绛夛級
+     * @param pageSize 杩斿洖缁撴灉鏁伴噺闄愬埗锛堥粯璁�50锛�
+     * @return 鍖归厤鐨勫尰闄㈠垪琛紙鎸夊尮閰嶅害鎺掑簭锛�
+     */
+    @GetMapping("/searchByKeywords")
+    public AjaxResult searchHospitalsByKeywords(
+            @RequestParam("searchText") String searchText,
+            @RequestParam(value = "pageSize", required = false, defaultValue = "50") Integer pageSize) {
+        
+        logger.info("鍩轰簬鍒嗚瘝鍖归厤鎼滅储鍖婚櫌锛歴earchText={}, pageSize={}", searchText, pageSize);
+        
+        if (searchText == null || searchText.trim().isEmpty()) {
+            return error("鎼滅储鏂囨湰涓嶈兘涓虹┖");
+        }
+        
+        try {
+            long startTime = System.currentTimeMillis();
+            
+            // 1. 瀵瑰墠绔紶鍏ョ殑鎼滅储鏂囨湰杩涜鍒嗚瘝
+            String searchKeywords = HospitalTokenizerUtil.tokenizeSearchText(searchText);
+            logger.info("鎼滅储鏂囨湰鍒嗚瘝缁撴灉锛歿}", searchKeywords);
+            
+            if (searchKeywords.isEmpty()) {
+                return success(new ArrayList<>());
+            }
+            
+            // 2. 灏嗗垎璇嶇粨鏋滄媶鍒嗕负鍏抽敭璇嶅垪琛紝鐢ㄤ簬鏁版嵁搴撻杩囨护
+            String[] keywordArray = searchKeywords.split(",");
+            List<String> keywordList = new ArrayList<>();
+            for (String keyword : keywordArray) {
+                String trimmed = keyword.trim();
+                if (!trimmed.isEmpty() && trimmed.length() >= 2) { // 鍙娇鐢�2涓瓧浠ヤ笂鐨勫叧閿瘝
+                    keywordList.add(trimmed);
+                }
+            }
+            
+            if (keywordList.isEmpty()) {
+                logger.warn("娌℃湁鏈夋晥鐨勫叧閿瘝鐢ㄤ簬鎼滅储");
+                return success(new ArrayList<>());
+            }
+            
+            logger.info("浣跨敤鍏抽敭璇嶈繘琛屾暟鎹簱棰勮繃婊�: {}", keywordList);
+            
+            // 3. 閫氳繃鏁版嵁搴撳眰闈㈤杩囨护锛屽彧鏌ヨ鍙兘鍖归厤鐨勫尰闄紙鑰屼笉鏄墍鏈夊尰闄級
+            List<TbHospData> candidateHospitals = tbHospDataMapper.selectTbHospDataByKeywords(keywordList, "0");
+            
+            long queryTime = System.currentTimeMillis();
+            logger.info("鏁版嵁搴撻杩囨护瀹屾垚锛屽�欓�夊尰闄㈡暟閲�: {}, 鑰楁椂: {}ms", candidateHospitals.size(), queryTime - startTime);
+                        
+            // 4. 鎻愬彇鍊欓�夊尰闄㈢殑鍦板尯鍚嶇О锛堜粠 hopsArea 瀛楁锛�
+            Set<String> districtNames = new HashSet<>();
+            for (TbHospData hospital : candidateHospitals) {
+                if (StringUtils.isNotBlank(hospital.getHopsArea())) {
+                    // 鎻愬彇鍦板尯鍚嶏紝绉婚櫎甯歌鍚庣紑
+                    String area = hospital.getHopsArea()
+                        .replace("鍖�", "")
+                        .replace("甯�", "")
+                        .replace("鍘�", "")
+                        .trim();
+                    if (area.length() > 0) {
+                        districtNames.add(area);
+                    }
+                }
+            }
+                        
+            logger.info("鎻愬彇鍒� {} 涓嫭鐗瑰湴鍖哄悕绉�", districtNames.size());
+                        
+            // 5. 瀵瑰�欓�夊尰闄㈣绠楀尮閰嶅垎鏁帮紝骞惰繃婊ゅ嚭鏈夊尮閰嶇殑鍖婚櫌
+            List<HospitalMatchResult> matchResults = new ArrayList<>();
+                        
+            long matchStartTime = System.currentTimeMillis();
+                        
+            for (TbHospData hospital : candidateHospitals) {
+                if (hospital.getHospKeywords() == null || hospital.getHospKeywords().isEmpty()) {
+                    continue;
+                }
+                            
+                // 璁$畻鍖归厤鍒嗘暟锛堜紶鍏ュ尰闄㈠悕绉板拰鍦板尯鍚嶇О闆嗗悎锛�
+                int matchScore = HospitalTokenizerUtil.calculateMatchScore(
+                    searchKeywords, 
+                    hospital.getHospKeywords(),
+                    hospital.getHospName(),
+                    districtNames
+                );
+                            
+                // 鍙繚鐣欏尮閰嶅垎鏁拌揪鍒伴槇鍊肩殑鍖婚櫌
+                if (matchScore >= MIN_MATCH_SCORE_THRESHOLD) {
+                    matchResults.add(new HospitalMatchResult(hospital, matchScore));
+                }
+            }
+                        
+            long matchTime = System.currentTimeMillis();
+            logger.info("鍖归厤璁$畻瀹屾垚锛屾壘鍒� {} 涓尮閰嶇殑鍖婚櫌锛堝垎鏁�>={}}锛夛紝鑰楁椂: {}ms", 
+                matchResults.size(), MIN_MATCH_SCORE_THRESHOLD, matchTime - matchStartTime);
+            
+            // 4. 鎸夊尮閰嶅垎鏁伴檷搴忔帓搴忥紝鍒嗘暟鐩稿悓鏃舵寜鍖婚櫌鍚嶇О闀垮害鍗囧簭鎺掑簭锛堝悕绉拌秺鐭秺闈犲墠锛�
+            matchResults.sort(Comparator
+                .comparingInt(HospitalMatchResult::getMatchScore).reversed()
+                .thenComparingInt(result -> result.getHospital().getHospName().length()));
+            
+            // 5. 闄愬埗杩斿洖鏁伴噺
+            if (pageSize != null && pageSize > 0 && matchResults.size() > pageSize) {
+                matchResults = matchResults.subList(0, pageSize);
+            }
+            
+            // 6. 杞崲涓篐ospData瀵硅薄杩斿洖锛堝寘鍚尮閰嶅垎鏁帮級
+            List<HospDataWithScore> result = new ArrayList<>();
+            for (HospitalMatchResult matchResult : matchResults) {
+                TbHospData tbHospData = matchResult.getHospital();
+                HospData hospData = convertToHospData(tbHospData);
+                result.add(new HospDataWithScore(hospData, matchResult.getMatchScore()));
+                logger.debug("鍖婚櫌: {}, 鍖归厤鍒嗘暟: {}", 
+                    hospData.getHospName(), matchResult.getMatchScore());
+            }
+            
+            logger.info("杩斿洖 {} 涓尰闄㈢粨鏋�", result.size());
+            
+            long totalTime = System.currentTimeMillis() - startTime;
+            logger.info("鎼滅储瀹屾垚 - 鎬昏�楁椂: {}ms, 鏁版嵁搴撴煡璇�: {}ms, 鍖归厤璁$畻: {}ms", 
+                totalTime, queryTime - startTime, matchTime - matchStartTime);
+            
+            return success(result);
+            
+        } catch (Exception e) {
+            logger.error("鍒嗚瘝鍖归厤鎼滅储澶辫触", e);
+            return error("鎼滅储澶辫触锛�" + e.getMessage());
+        }
+    }
+    
+    /**
+     * 灏員bHospData杞崲涓篐ospData
+     */
+    private HospData convertToHospData(TbHospData tbHospData) {
+        HospData hospData = new HospData();
+        hospData.setHospId(tbHospData.getLegacyHospId());
+        hospData.setHospName(tbHospData.getHospName());
+        hospData.setHospCityId(tbHospData.getHospCityId());
+        hospData.setHospShort(tbHospData.getHospShort());
+        hospData.setHopsProvince(tbHospData.getHopsProvince());
+        hospData.setHopsCity(tbHospData.getHopsCity());
+        hospData.setHopsArea(tbHospData.getHopsArea());
+        hospData.setHospAddress(tbHospData.getHospAddress());
+        hospData.setHospTel(tbHospData.getHospTel());
+        hospData.setHospUnitId(tbHospData.getHospUnitId());
+        hospData.setHospState(tbHospData.getHospState());
+        hospData.setHospOaId(tbHospData.getHospOaId());
+        hospData.setHospIntroducerId(tbHospData.getHospIntroducerId());
+        if (tbHospData.getHospIntroducerDate() != null) {
+            hospData.setHospIntroducerDate(tbHospData.getHospIntroducerDate().toString());
+        }
+        hospData.setHospLevel(tbHospData.getHospLevel());
+        return hospData;
+    }
+    
+    /**
+     * 鍖婚櫌鍖归厤缁撴灉鍐呴儴绫�
+     */
+    private static class HospitalMatchResult {
+        private TbHospData hospital;
+        private int matchScore;
+        
+        public HospitalMatchResult(TbHospData hospital, int matchScore) {
+            this.hospital = hospital;
+            this.matchScore = matchScore;
+        }
+        
+        public TbHospData getHospital() {
+            return hospital;
+        }
+        
+        public int getMatchScore() {
+            return matchScore;
+        }
+    }
+    
+    /**
+     * 鍖婚櫌鏁版嵁涓庡尮閰嶅垎鏁板寘瑁呯被
+     */
+    private static class HospDataWithScore {
+        private HospData hospital;
+        private int matchScore;
+        
+        public HospDataWithScore(HospData hospital, int matchScore) {
+            this.hospital = hospital;
+            this.matchScore = matchScore;
+        }
+        
+        public HospData getHospital() {
+            return hospital;
+        }
+        
+        public int getMatchScore() {
+            return matchScore;
+        }
+    }
 }

--
Gitblit v1.9.1