From 51b9df7d9e907506ce565fd47a7aa4661a4139ea Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期四, 13 十一月 2025 23:03:12 +0800
Subject: [PATCH] feat:优化增加自动匹配识别

---
 app/pages/task/create-emergency.vue                                               |  512 +++++++++++++++++++++++++++++++++++++++++++++++++++
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/HospDataController.java |   43 +++
 app/api/hospital.js                                                               |   24 +
 3 files changed, 561 insertions(+), 18 deletions(-)

diff --git a/app/api/hospital.js b/app/api/hospital.js
index dc1d7d0..39e474f 100644
--- a/app/api/hospital.js
+++ b/app/api/hospital.js
@@ -4,14 +4,16 @@
  * 鎼滅储鍖婚櫌
  * @param {string} keyword 鎼滅储鍏抽敭璇嶏紙鍖婚櫌鍚嶇О銆佸湴鍧�銆佺畝绉般�佺渷甯傚尯锛�
  * @param {number} deptId 閮ㄩ棬ID锛堢敤浜庢牴鎹儴闂ㄥ尯鍩熼厤缃繃婊ゅ尰闄級
+ * @param {number} limit 杩斿洖缁撴灉鏁伴噺闄愬埗锛堥粯璁�50锛屽湪鍓嶇澶勭悊锛�
  */
-export function searchHospitals(keyword, deptId) {
+export function searchHospitals(keyword, deptId, limit = 50) {
   return request({
     url: '/system/hospital/search',
     method: 'get',
     params: {
       keyword: keyword,
-      deptId: deptId
+      deptId: deptId,
+      pageSize: limit
     }
   })
 }
@@ -34,14 +36,16 @@
  * 鑾峰彇甯哥敤杞嚭鍖婚櫌鍒楄〃
  * @param {string} serviceOrdClass 鍒嗗叕鍙哥紪鐮侊紙service_order_class锛�
  * @param {string} region 鍦板煙鍏抽敭璇嶏紙鍙�夛級
+ * @param {number} limit 杩斿洖缁撴灉鏁伴噺闄愬埗锛堥粯璁�50锛�
  */
-export function getFrequentOutHospitals(serviceOrdClass, region) {
+export function getFrequentOutHospitals(serviceOrdClass, region, limit = 50) {
   return request({
     url: '/system/hospital/frequent/out',
     method: 'get',
     params: {
       serviceOrdClass: serviceOrdClass,
-      region: region
+      region: region,
+      pageSize: limit
     }
   })
 }
@@ -50,14 +54,16 @@
  * 鑾峰彇甯哥敤杞叆鍖婚櫌鍒楄〃
  * @param {string} serviceOrdClass 鍒嗗叕鍙哥紪鐮侊紙service_order_class锛�
  * @param {string} region 鍦板煙鍏抽敭璇嶏紙鍙�夛級
+ * @param {number} limit 杩斿洖缁撴灉鏁伴噺闄愬埗锛堥粯璁�50锛�
  */
-export function getFrequentInHospitals(serviceOrdClass, region) {
+export function getFrequentInHospitals(serviceOrdClass, region, limit = 50) {
   return request({
     url: '/system/hospital/frequent/in',
     method: 'get',
     params: {
       serviceOrdClass: serviceOrdClass,
-      region: region
+      region: region,
+      pageSize: limit
     }
   })
 }
@@ -66,14 +72,16 @@
  * 鏍规嵁閮ㄩ棬鍖哄煙閰嶇疆鎼滅储鍖婚櫌锛堟敮鎸佸绾у尯鍩燂級
  * @param {string} keyword 鎼滅储鍏抽敭璇�
  * @param {number} deptId 閮ㄩ棬ID
+ * @param {number} limit 杩斿洖缁撴灉鏁伴噺闄愬埗锛堥粯璁�50锛屽湪鍓嶇澶勭悊锛�
  */
-export function searchHospitalsByDeptRegion(keyword, deptId) {
+export function searchHospitalsByDeptRegion(keyword, deptId, limit = 50) {
   return request({
     url: '/system/hospital/search/by-dept-region',
     method: 'get',
     params: {
       keyword: keyword,
-      deptId: deptId
+      deptId: deptId,
+      pageSize: limit
     }
   })
 }
diff --git a/app/pages/task/create-emergency.vue b/app/pages/task/create-emergency.vue
index 8154fcb..6cd7631 100644
--- a/app/pages/task/create-emergency.vue
+++ b/app/pages/task/create-emergency.vue
@@ -5,6 +5,10 @@
         <uni-icons type="arrowleft" size="20"></uni-icons>
       </view>
       <view class="title">鍒涘缓杞繍浠诲姟</view>
+      <view class="smart-parse-btn" @click="showSmartParsePopup">
+        <uni-icons type="compose" size="20" color="#007AFF"></uni-icons>
+        <text>鏅鸿兘璇嗗埆</text>
+      </view>
     </view>
     
     <view class="form-section">
@@ -440,6 +444,38 @@
       </view>
     </uni-popup>
     
+   <!-- 鏅鸿兘璇嗗埆寮圭獥 -->
+    <uni-popup ref="smartParsePopup" type="bottom" :safe-area="true">
+      <view class="smart-parse-popup">
+        <view class="popup-header">
+          <view class="popup-title">鏅鸿兘璇嗗埆</view>
+          <view class="popup-close" @click="closeSmartParsePopup">
+            <uni-icons type="closeempty" size="24" color="#333"></uni-icons>
+          </view>
+        </view>
+        
+        <view class="parse-content">
+          <view class="parse-tip">
+            <uni-icons type="info" size="18" color="#007AFF"></uni-icons>
+            <text>绮樿创鎴栬緭鍏ユ枃鏈紝濡傦細"鎮h�呭紶涓夛紝鐢佃瘽13800138000锛屼粠骞垮窞鏌愭煇鍖婚櫌杞叆娣卞湷鏌愭煇涓績锛岃垂鐢骏680"</text>
+          </view>
+          <textarea
+            class="parse-textarea"
+            placeholder="璇峰湪姝ょ矘璐存垨杈撳叆杞繍淇℃伅..."
+            v-model="rawText"
+            :maxlength="-1"
+          />
+        </view>
+        
+        <view class="popup-footer">
+          <button class="cancel-btn" @click="closeSmartParsePopup">鍙栨秷</button>
+          <button class="confirm-btn" @click="parseFreeText" :disabled="parseLoading">
+            {{ parseLoading ? '璇嗗埆涓�...' : '寮�濮嬭瘑鍒�' }}
+          </button>
+        </view>
+      </view>
+    </uni-popup>
+    
     <!-- 鐥呮儏閫夋嫨寮圭獥 -->
     <uni-popup ref="diseasePopup" type="bottom" :safe-area="true">
       <view class="disease-selector-popup">
@@ -606,7 +642,10 @@
       addressCoordinates: {
         hospitalOutAddress: null,
         hospitalInAddress: null
-      }
+      },
+      // 鏅鸿兘璇嗗埆鐩稿叧
+      rawText: '',
+      parseLoading: false
     }
   },
   computed: {
@@ -1952,8 +1991,371 @@
       }).catch(() => {})
     },
     
-    goBack() {
+   goBack() {
       uni.navigateBack()
+    },
+    
+    // ==================== 鏅鸿兘璇嗗埆鐩稿叧鏂规硶 ====================
+    
+    // 鏄剧ず鏅鸿兘璇嗗埆寮圭獥
+    showSmartParsePopup() {
+      this.rawText = ''
+      this.$refs.smartParsePopup.open()
+    },
+    
+    // 鍏抽棴鏅鸿兘璇嗗埆寮圭獥
+    closeSmartParsePopup() {
+      this.$refs.smartParsePopup.close()
+      this.rawText = ''
+    },
+    
+    // 瑙f瀽鑷敱鏂囨湰骞跺~鍏呰〃鍗�
+    parseFreeText() {
+      const text = (this.rawText || '').trim()
+      if (!text) {
+        this.$modal.showToast('璇峰厛绮樿创鎴栬緭鍏ユ枃鏈�')
+        return
+      }
+      this.parseLoading = true
+
+      const result = {
+        patientName: this.extractPatientName(text),
+        phone: this.extractPhone(text),
+        hospitalOutName: this.extractHospital(text, 'out'),
+        hospitalInName: this.extractHospital(text, 'in'),
+        departmentOut: this.extractDepartment(text, 'out'),
+        departmentIn: this.extractDepartment(text, 'in'),
+        price: this.extractPrice(text)
+      }
+
+      // 搴旂敤鍩虹瀛楁
+      if (result.patientName) this.taskForm.patient.name = result.patientName
+      if (result.phone) this.taskForm.patient.phone = result.phone
+      if (result.price) this.taskForm.price = result.price
+      
+      // 搴旂敤绉戝淇℃伅锛堝尮閰� departmentOptions 涓殑鏁版嵁锛�
+      if (result.departmentOut) {
+        const deptOut = this.matchDepartment(result.departmentOut)
+        if (deptOut) {
+          this.taskForm.hospitalOut.department = deptOut.text
+          this.taskForm.hospitalOut.departmentId = deptOut.id
+        }
+      }
+      if (result.departmentIn) {
+        const deptIn = this.matchDepartment(result.departmentIn)
+        if (deptIn) {
+          this.taskForm.hospitalIn.department = deptIn.text
+          this.taskForm.hospitalIn.departmentId = deptIn.id
+        }
+      }
+
+      // 澶勭悊鍖婚櫌鍚嶇О 鈫� 绮剧‘鍖归厤鍖婚櫌骞惰ˉ鍏ㄥ湴鍧�涓嶪D锛堜笉闄愬埗鍒嗗叕鍙稿尯鍩燂級
+      Promise.all([
+        this.findHospitalByName(result.hospitalOutName, 'out', false),
+        this.findHospitalByName(result.hospitalInName, 'in', false)
+      ])
+      .then(([outHosp, inHosp]) => {
+        if (outHosp) {
+          this.taskForm.hospitalOut.id = outHosp.hospId
+          this.taskForm.hospitalOut.name = outHosp.hospName
+          if (outHosp.hospName !== '瀹朵腑') {
+            this.taskForm.hospitalOut.address = this.buildFullAddress(outHosp)
+            this.taskForm.hospitalOut.city = outHosp.hopsCity || ''
+            this.hospitalOutSearchKeyword = outHosp.hospName
+          } else {
+            this.taskForm.hospitalOut.address = ''
+            this.taskForm.hospitalOut.department = '鍏跺畠'
+            this.hospitalOutSearchKeyword = '瀹朵腑'
+          }
+        } else if (result.hospitalOutName) {
+          this.taskForm.hospitalOut.name = result.hospitalOutName
+          this.hospitalOutSearchKeyword = result.hospitalOutName
+        }
+
+        if (inHosp) {
+          this.taskForm.hospitalIn.id = inHosp.hospId
+          this.taskForm.hospitalIn.name = inHosp.hospName
+          if (inHosp.hospName !== '瀹朵腑') {
+            this.taskForm.hospitalIn.address = this.buildFullAddress(inHosp)
+            this.taskForm.hospitalIn.city = inHosp.hopsCity || ''
+            this.hospitalInSearchKeyword = inHosp.hospName
+          } else {
+            this.taskForm.hospitalIn.address = ''
+            this.taskForm.hospitalIn.department = '鍏跺畠'
+            this.hospitalInSearchKeyword = '瀹朵腑'
+          }
+        } else if (result.hospitalInName) {
+          this.taskForm.hospitalIn.name = result.hospitalInName
+          this.hospitalInSearchKeyword = result.hospitalInName
+        }
+
+        // 鑻ヤ袱绔湴鍧�瀹屾暣锛岃嚜鍔ㄨ绠楄窛绂讳笌鎴愪氦浠�
+        if (this.taskForm.hospitalOut.address && this.taskForm.hospitalIn.address &&
+            this.taskForm.hospitalOut.name !== '瀹朵腑' && this.taskForm.hospitalIn.name !== '瀹朵腑') {
+          this.calculateHospitalDistance()
+        }
+      })
+      .catch(err => {
+        console.error('鍖婚櫌鍖归厤澶辫触:', err)
+      })
+      .finally(() => {
+        this.parseLoading = false
+        this.closeSmartParsePopup()
+        this.$modal.showToast('璇嗗埆瀹屾垚锛岃鏍稿鑷姩濉厖缁撴灉')
+      })
+    },
+
+    // 鎻愬彇鎵嬫満鍙凤紙浼樺厛鍖归厤绉诲姩鍙凤紝娆″尮閰嶅骇鏈猴級
+    extractPhone(text) {
+      // 鍏堝幓闄ゆ枃鏈腑鐨勭┖鏍硷紝鍐嶈繘琛屽尮閰�
+      const cleanText = text.replace(/\s+/g, '')
+      
+      // 鍖归厤11浣嶆墜鏈哄彿锛堟敮鎸佸師鏂囨湰涓湁绌烘牸鐨勬儏鍐碉級
+      const mobile = cleanText.match(/(?<!\d)(1[3-9]\d{9})(?!\d)/)
+      if (mobile) return mobile[1]
+      
+      // 鍖归厤搴ф満鍙凤紙鏀寔甯﹀尯鍙峰拰杩炲瓧绗︼級
+      const landline = cleanText.match(/0\d{2,3}-?\d{7,8}/)
+      if (landline) return landline[0]
+      
+      // 鍏滃簳锛氬湪鍘熸枃鏈腑鏌ユ壘甯︾┖鏍肩殑鎵嬫満鍙锋牸寮忥紙濡傦細182 8569 1756锛�
+      const mobileWithSpace = text.match(/(?:鐢佃瘽|鎵嬫満|鑱旂郴|tel|phone)[锛�:\s]*([1][3-9][\d\s]{9,15})/i)
+      if (mobileWithSpace) {
+        const cleanMobile = mobileWithSpace[1].replace(/\s+/g, '')
+        if (/^1[3-9]\d{9}$/.test(cleanMobile)) {
+          return cleanMobile
+        }
+      }
+      
+      // 鏈�鍚庡皾璇曪細鐩存帴鏌ユ壘浠绘剰甯︾┖鏍肩殑11浣嶆暟瀛楃粍鍚�
+      const anyMobile = text.match(/([1][3-9][\d\s]{9,15})/)
+      if (anyMobile) {
+        const cleanAny = anyMobile[1].replace(/\s+/g, '')
+        if (/^1[3-9]\d{9}$/.test(cleanAny)) {
+          return cleanAny
+        }
+      }
+      
+      return ''
+    },
+
+    // 鎻愬彇鎮h�呭鍚嶏紙甯歌鍏抽敭璇嶅墠缂�锛�
+    extractPatientName(text) {
+      const m = text.match(/(?:鎮h�厊鐥呬汉|濮撳悕|鑱旂郴浜�)[锛�: ]?\s*([\u4e00-\u9fa5]{2,4})/)
+      return m ? m[1] : ''
+    },
+
+    // 鎻愬彇鎴愪氦浠凤紙鏀寔锟�/鍏�/RMB绛夛級
+    extractPrice(text) {
+      const m1 = text.match(/(?:鎴愪氦浠穦浠锋牸|璐圭敤|鏀惰垂|鎬讳环|鍏�)[锛�: ]?\s*(?:锟楼|RMB|浜烘皯甯�)?\s*([0-9]+(?:\.[0-9]{1,2})?)/i)
+      if (m1) return parseFloat(m1[1]).toFixed(2)
+      const m2 = text.match(/(?:锟楼)\s*([0-9]+(?:\.[0-9]{1,2})?)/)
+      if (m2) return parseFloat(m2[1]).toFixed(2)
+      const m3 = text.match(/([0-9]+(?:\.[0-9]{1,2})?)\s*(?:鍏億浜烘皯甯亅RMB)/i)
+      if (m3) return parseFloat(m3[1]).toFixed(2)
+      return ''
+    },
+
+    // 鎻愬彇鍖婚櫌鍚嶇О锛堝熀浜庤涔夋爣璁帮紝鏀寔绠�绉板"鐪佸尰"锛�
+    extractHospital(text, type) {
+      // 鍏堝皾璇曡涔夋爣璁版彁鍙�
+      const outReg = /(?:杞嚭|鏉ヨ嚜|浠�)[锛�: ]?\s*([^\s锛�,銆傦紱;杞琞+?(?:鍖婚櫌|涓績|鍗敓闄鎬ユ晳涓績|瀹朵腑|鐪佸尰|甯傚尰|鍖哄尰|鍘垮尰|浜烘皯鍖婚櫌|涓尰闄濡囧辜|鍎跨鍖婚櫌))/
+      const inReg  = /(?:杞叆|鑷硘鍓嶅線|鍒皘鍘诲線|杞洖)[锛�: ]?\s*([^\s锛�,銆傦紱;杞琞+?(?:鍖婚櫌|涓績|鍗敓闄鎬ユ晳涓績|瀹朵腑|鐪佸尰|甯傚尰|鍖哄尰|鍘垮尰|浜烘皯鍖婚櫌|涓尰闄濡囧辜|鍎跨鍖婚櫌))/
+      const reg = type === 'out' ? outReg : inReg
+      const m = text.match(reg)
+      if (m) {
+        // 鍘婚櫎鍙兘鍖呭惈鐨勬ゼ鏍嬨�佹ゼ灞傘�佺瀹ょ瓑淇℃伅
+        let hospitalName = m[1]
+        // 鍘婚櫎妤兼爧淇℃伅锛堝锛氫笢涓�鍙锋ゼ銆丄鏍嬬瓑锛�
+        hospitalName = hospitalName.replace(/[涓滆タ鍗楀寳涓璢?[涓�浜屼笁鍥涗簲鍏竷鍏節鍗�0-9]+鍙�?妤�.*/g, '')
+        // 鍘婚櫎妤煎眰淇℃伅锛堝锛氬洓妤笺��3F绛夛級
+        hospitalName = hospitalName.replace(/[涓�浜屼笁鍥涗簲鍏竷鍏節鍗�0-9]+[妤煎眰F].*/g, '')
+        return hospitalName.trim()
+      }
+      
+      // 鏃犺涔夋爣璁版椂锛屽厹搴曟彁鍙栭涓�"鍚尰闄�/涓績/瀹朵腑/绠�绉�"鐨勭墖娈�
+      const any = text.match(/([^\s锛�,銆傦紱;杞琞+?(?:鍖婚櫌|涓績|鍗敓闄鎬ユ晳涓績|瀹朵腑|鐪佸尰|甯傚尰|鍖哄尰|鍘垮尰|浜烘皯鍖婚櫌|涓尰闄濡囧辜|鍎跨鍖婚櫌))/g)
+      if (any && any.length > 0) {
+        if (type === 'out') {
+          let name = any[0]
+          name = name.replace(/[涓滆タ鍗楀寳涓璢?[涓�浜屼笁鍥涗簲鍏竷鍏節鍗�0-9]+鍙�?妤�.*/g, '')
+          name = name.replace(/[涓�浜屼笁鍥涗簲鍏竷鍏節鍗�0-9]+[妤煎眰F].*/g, '')
+          return name.trim()
+        }
+        if (type === 'in') {
+          let name = any[1] || any[0]
+          name = name.replace(/[涓滆タ鍗楀寳涓璢?[涓�浜屼笁鍥涗簲鍏竷鍏節鍗�0-9]+鍙�?妤�.*/g, '')
+          name = name.replace(/[涓�浜屼笁鍥涗簲鍏竷鍏節鍗�0-9]+[妤煎眰F].*/g, '')
+          return name.trim()
+        }
+      }
+      return ''
+    },
+    
+    // 鍖归厤绉戝锛堜紭鍏堜娇鐢� departmentOptions 涓殑鏁版嵁锛�
+    matchDepartment(deptName) {
+      if (!deptName || !this.departmentOptions || this.departmentOptions.length === 0) {
+        return null
+      }
+      
+      const normalized = deptName.trim().toUpperCase()
+      
+      // 1. 绮剧‘鍖归厤锛堜笉鍖哄垎澶у皬鍐欙級
+      let matched = this.departmentOptions.find(d => 
+        d.text.toUpperCase() === normalized
+      )
+      if (matched) return matched
+      
+      // 2. 鍖呭惈鍖归厤锛堢瀹ゅ悕鍖呭惈璇嗗埆鍒扮殑鍏抽敭璇嶏級
+      matched = this.departmentOptions.find(d => 
+        d.text.toUpperCase().includes(normalized) || 
+        normalized.includes(d.text.toUpperCase())
+      )
+      if (matched) return matched
+      
+      // 3. 妯$硦鍖归厤锛堝幓闄�"绉�"銆�"瀹�"绛夊悗缂�鍐嶅尮閰嶏級
+      const cleanedInput = normalized.replace(/[绉戝閮╙/g, '')
+      matched = this.departmentOptions.find(d => {
+        const cleanedDept = d.text.toUpperCase().replace(/[绉戝閮╙/g, '')
+        return cleanedDept === cleanedInput || 
+               cleanedDept.includes(cleanedInput) || 
+               cleanedInput.includes(cleanedDept)
+      })
+      if (matched) return matched
+      
+      return null
+    },
+    
+    // 鎻愬彇绉戝淇℃伅
+    extractDepartment(text, type) {
+      // 甯歌绉戝鍏抽敭璇嶏紙浣滀负鍏滃簳鏂规锛�
+      const departments = [
+        'ICU', 'NICU', 'PICU', 'CCU', 'EICU',
+        '閲嶇棁鐩戞姢瀹�', '鎬ヨ瘖绉�', '闂ㄨ瘖', '浣忛櫌閮�',
+        '鍐呯', '澶栫', '濡囦骇绉�', '鍎跨', '楠ㄧ', '绁炵粡绉�',
+        '蹇冨唴绉�', '蹇冨绉�', '鍛煎惛绉�', '娑堝寲绉�', '鑲惧唴绉�',
+        '琛�娑茬', '鑲跨槫绉�', '鎰熸煋绉�', '鐨偆绉�', '鐪肩',
+        '鑰抽蓟鍠夌', '鍙h厰绉�', '涓尰绉�', '搴峰绉�', '绮剧绉�',
+        '娉屽翱绉�', '鍐呭垎娉岀', '椋庢箍绉�', '鏅绉�', '鑳稿绉�',
+        '绁炵粡澶栫', '鏁村舰绉�', '鐑т激绉�', '楹婚唹绉�', '鏀惧皠绉�',
+        '妫�楠岀', '鐥呯悊绉�', '鑽墏绉�', '钀ュ吇绉�'
+      ]
+      
+      // 浼樺厛灏濊瘯浠� departmentOptions 涓尮閰�
+      if (this.departmentOptions && this.departmentOptions.length > 0) {
+        // 鏋勫缓 departmentOptions 鐨勫尮閰嶆ā寮忥紙鎸夐暱搴﹀�掑簭锛�
+        const optionTexts = this.departmentOptions.map(d => d.text).sort((a, b) => b.length - a.length)
+        const optionPattern = optionTexts.map(t => t.replace(/[()锛堬級]/g, '\\$&')).join('|')
+        
+        if (optionPattern) {
+          const regex = new RegExp(`(${optionPattern})`, 'gi')
+          const matches = text.match(regex)
+          
+          if (matches && matches.length > 0) {
+            // 濡傛灉鏄浆鍑猴紝鍙栫涓�涓瀹わ紱濡傛灉鏄浆鍏ワ紝鍙栨渶鍚庝竴涓瀹�
+            return type === 'out' ? matches[0] : matches[matches.length - 1]
+          }
+        }
+      }
+      
+      // 鍏滃簳锛氫娇鐢ㄩ粯璁ょ瀹ゅ垪琛ㄥ尮閰�
+      const sortedDepts = departments.sort((a, b) => b.length - a.length)
+      const deptPattern = sortedDepts.join('|')
+      
+      const regex = new RegExp(`(${deptPattern})`, 'g')
+      const matches = text.match(regex)
+      
+      if (matches && matches.length > 0) {
+        // 濡傛灉鏄浆鍑猴紝鍙栫涓�涓瀹わ紱濡傛灉鏄浆鍏ワ紝鍙栨渶鍚庝竴涓瀹�
+        return type === 'out' ? matches[0] : matches[matches.length - 1]
+      }
+      
+      return ''
+    },
+
+    // 閫氳繃鍚嶇О鍖归厤鍖婚櫌锛坮estrictRegion=false 鏃跺叏灞�鏌ヨ锛�
+    findHospitalByName(name, type, restrictRegion = true) {
+      if (!name) return Promise.resolve(null)
+      const normalized = name.trim()
+
+      // 鐗规畩澶勭悊"瀹朵腑"
+      if (normalized === '瀹朵腑') {
+        // 鏌ヨ鍖婚櫌搴撲腑鐨�"瀹朵腑"璁板綍
+        const deptId = this.selectedOrganizationId || null
+        const queryPromise = restrictRegion && deptId
+          ? searchHospitalsByDeptRegion('瀹朵腑', deptId, 50)
+          : searchHospitals('瀹朵腑', null, 50)
+        
+        return queryPromise.then(res => {
+          const list = res.data || []
+          // 鏌ユ壘鍚嶇О涓�"瀹朵腑"鐨勫尰闄㈣褰�
+          const homeHospital = list.find(h => h.hospName === '瀹朵腑')
+          if (homeHospital) {
+            return homeHospital
+          }
+          // 濡傛灉娌℃湁鎵惧埌锛岃繑鍥為粯璁ょ粨鏋�
+          return {
+            hospId: null,
+            hospName: '瀹朵腑',
+            hopsCity: '',
+            hospAddress: ''
+          }
+        }).catch(() => {
+          // 鏌ヨ澶辫触锛岃繑鍥為粯璁ょ粨鏋�
+          return {
+            hospId: null,
+            hospName: '瀹朵腑',
+            hopsCity: '',
+            hospAddress: ''
+          }
+        })
+      }
+
+      // restrictRegion=false 鏃惰蛋鍏ㄩ噺鏌ヨ锛泃rue 涓旀湁 deptId 鏃惰蛋鍖哄煙鎺ュ彛
+      const deptId = this.selectedOrganizationId || null
+      const queryPromise = (restrictRegion && deptId)
+        ? searchHospitalsByDeptRegion(normalized, deptId, 50)
+        : searchHospitals(normalized, null, 50)
+
+      return queryPromise.then(res => {
+        const list = res.data || []
+        if (!list.length) return null
+        
+        // 鑷姩閫夋嫨绗竴涓潪"瀹朵腑"鐨勫尯闄紝濡傛灉鍏ㄦ槸"瀹朵腑"鍒欓�夌涓�涓�
+        const best = this.pickBestHospitalMatch(list, normalized)
+        return best || null
+      })
+    },
+
+    // 鍦ㄥ�欓�変腑閫夋嫨鏈�浼樺尮閰嶏紙鏀寔绠�绉板尮閰嶃�佸寘鍚笌闀垮害鎺ヨ繎锛�
+    pickBestHospitalMatch(list, name) {
+      const n = name.trim()
+      
+      // 杩囨护鎺�"瀹朵腑"锛屼紭鍏堥�夋嫨鐪熷疄鍖婚櫌
+      const realHospitals = list.filter(h => h.hospName !== '瀹朵腑')
+      const searchList = realHospitals.length > 0 ? realHospitals : list
+      
+      // 1. 瀹屽叏鐩哥瓑锛堟寮忓悕锛�
+      let best = searchList.find(h => (h.hospName || '').trim() === n)
+      if (best) return best
+      // 2. 瀹屽叏鐩哥瓑锛堢畝绉帮級
+      best = searchList.find(h => (h.hospShort || '').trim() === n)
+      if (best) return best
+      // 3. 鍖呭惈锛堟寮忓悕锛�
+      best = searchList.find(h => (h.hospName || '').includes(n) || n.includes((h.hospName || '')))
+      if (best) return best
+      // 4. 鍖呭惈锛堢畝绉帮級
+      best = searchList.find(h => (h.hospShort || '').includes(n) || n.includes((h.hospShort || '')))
+      if (best) return best
+      // 5. 闀垮害鏈�鎺ヨ繎
+      best = [...searchList].sort((a, b) => {
+        const da = Math.abs((a.hospName || '').length - n.length)
+        const db = Math.abs((b.hospName || '').length - n.length)
+        return da - db
+      })[0]
+      
+      // 濡傛灉娌℃湁鎵惧埌浠讳綍鍖归厤锛岃繑鍥炵涓�涓�
+      return best || searchList[0] || null
     },
     
     // 鍚堝苟鍖婚櫌鍦板潃锛堢渷 + 甯� + 鍖� + 璇︾粏鍦板潃锛�
@@ -2048,9 +2450,24 @@
     }
     
     .title {
+      flex: 1;
       font-size: 36rpx;
       font-weight: bold;
       color: #333;
+    }
+    
+    .smart-parse-btn {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      justify-content: center;
+      padding: 10rpx 20rpx;
+      
+      text {
+        font-size: 22rpx;
+        color: #007AFF;
+        margin-top: 4rpx;
+      }
     }
   }
   
@@ -2485,6 +2902,97 @@
   }
 }
 
+// 鏅鸿兘璇嗗埆寮圭獥鏍峰紡
+.smart-parse-popup {
+  background-color: white;
+  border-radius: 20rpx 20rpx 0 0;
+  max-height: 80vh;
+  display: flex;
+  flex-direction: column;
+  
+  .popup-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 30rpx;
+    border-bottom: 1rpx solid #f0f0f0;
+    flex-shrink: 0;
+    
+    .popup-title {
+      font-size: 32rpx;
+      font-weight: bold;
+      color: #333;
+    }
+    
+    .popup-close {
+      padding: 10rpx;
+    }
+  }
+  
+  .parse-content {
+    flex: 1;
+    padding: 30rpx;
+    overflow-y: auto;
+    
+    .parse-tip {
+      display: flex;
+      align-items: flex-start;
+      padding: 20rpx;
+      background-color: #f0f7ff;
+      border-radius: 10rpx;
+      margin-bottom: 20rpx;
+      
+      text {
+        flex: 1;
+        margin-left: 10rpx;
+        font-size: 24rpx;
+        color: #666;
+        line-height: 1.6;
+      }
+    }
+    
+    .parse-textarea {
+      width: 100%;
+      min-height: 300rpx;
+      padding: 20rpx;
+      border: 1rpx solid #eee;
+      border-radius: 10rpx;
+      font-size: 28rpx;
+      line-height: 1.6;
+    }
+  }
+  
+  .popup-footer {
+    display: flex;
+    padding: 20rpx 30rpx;
+    border-top: 1rpx solid #f0f0f0;
+    gap: 20rpx;
+    flex-shrink: 0;
+    
+    button {
+      flex: 1;
+      height: 80rpx;
+      border-radius: 10rpx;
+      font-size: 30rpx;
+    }
+    
+    .cancel-btn {
+      background-color: #f5f5f5;
+      color: #666;
+    }
+    
+    .confirm-btn {
+      background-color: #007AFF;
+      color: white;
+      
+      &[disabled] {
+        background-color: #ccc;
+        color: #999;
+      }
+    }
+  }
+}
+
 // 鐥呮儏閫夋嫨寮圭獥鏍峰紡
 .disease-selector-popup {
   background-color: white;
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 085cdc4..d4f92b1 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
@@ -40,7 +40,8 @@
     @GetMapping("/search")
     public AjaxResult searchHospitals(
             @RequestParam(value = "keyword", required = false) String keyword,
-            @RequestParam(value = "deptId", required = false) Long deptId) {
+            @RequestParam(value = "deptId", required = false) Long deptId,
+            @RequestParam(value = "pageSize", required = false, defaultValue = "50") Integer pageSize) {
         List<HospData> list;
         
         // 濡傛灉keyword涓虹┖锛屼娇鐢ㄩ儴闂ㄥ尯鍩熻繃婊ゆ煡璇�
@@ -54,6 +55,11 @@
            
                 list = hospDataMapper.searchHospitals(keyword, "");
             
+        }
+        
+        // 闄愬埗杩斿洖鏁伴噺
+        if (pageSize != null && pageSize > 0 && list.size() > pageSize) {
+            list = list.subList(0, pageSize);
         }
         
         // 纭繚"瀹朵腑"鍦ㄧ粨鏋滀腑
@@ -81,11 +87,13 @@
      * 鑾峰彇甯哥敤杞嚭鍖婚櫌鍒楄〃锛堜粠MySQL tb_hosp_data琛ㄦ煡璇級
      * @param serviceOrdClass 鍒嗗叕鍙哥紪鐮侊紙service_order_class锛�
      * @param region 鍦板煙鍏抽敭璇嶏紙鍙�夛級
+     * @param pageSize 杩斿洖缁撴灉鏁伴噺闄愬埗锛堥粯璁�50锛�
      */
     @GetMapping("/frequent/out")
     public AjaxResult getFrequentOutHospitals(
             @RequestParam("serviceOrdClass") String serviceOrdClass,
-            @RequestParam(value = "region", required = false) String region) {
+            @RequestParam(value = "region", required = false) String region,
+            @RequestParam(value = "pageSize", required = false, defaultValue = "50") Integer pageSize) {
         // 鏌ヨ甯哥敤杞嚭鍖婚櫌ID鍒楄〃
         logger.info("getFrequentOutHospitals 浼犲叆鐨� serviceOrdClass :{}",serviceOrdClass);
         List<Integer> hospIds = sqlHospDataService.selectFrequentOutHospitalIds(serviceOrdClass);
@@ -96,6 +104,11 @@
 
         // 鏍规嵁ID鍒楄〃鏌ヨ鍖婚櫌璇︽儏
         List<HospData> hospitals = hospDataMapper.selectHospDataByIds(hospIds, region);
+        
+        // 闄愬埗杩斿洖鏁伴噺
+        if (pageSize != null && pageSize > 0 && hospitals.size() > pageSize) {
+            hospitals = hospitals.subList(0, pageSize);
+        }
 
         return success(hospitals);
     }
@@ -104,11 +117,13 @@
      * 鑾峰彇甯哥敤杞叆鍖婚櫌鍒楄〃锛堜粠MySQL tb_hosp_data琛ㄦ煡璇級
      * @param serviceOrdClass 鍒嗗叕鍙哥紪鐮侊紙service_order_class锛�
      * @param region 鍦板煙鍏抽敭璇嶏紙鍙�夛級
+     * @param pageSize 杩斿洖缁撴灉鏁伴噺闄愬埗锛堥粯璁�50锛�
      */
     @GetMapping("/frequent/in")
     public AjaxResult getFrequentInHospitals(
             @RequestParam("serviceOrdClass") String serviceOrdClass,
-            @RequestParam(value = "region", required = false) String region) {
+            @RequestParam(value = "region", required = false) String region,
+            @RequestParam(value = "pageSize", required = false, defaultValue = "50") Integer pageSize) {
         // 鏌ヨ甯哥敤杞叆鍖婚櫌ID鍒楄〃
         logger.info("getFrequentInHospitals 浼犲叆鐨� serviceOrdClass {}",serviceOrdClass);
         List<Integer> hospIds = sqlHospDataService.selectFrequentInHospitalIds(serviceOrdClass);
@@ -120,29 +135,41 @@
 
         // 鏍规嵁ID鍒楄〃鏌ヨ鍖婚櫌璇︽儏
         List<HospData> hospitals = hospDataMapper.selectHospDataByIds(hospIds, region);
+        
+        // 闄愬埗杩斿洖鏁伴噺
+        if (pageSize != null && pageSize > 0 && hospitals.size() > pageSize) {
+            hospitals = hospitals.subList(0, pageSize);
+        }
+        
         if(homeHospId>0) {
-
-         HospData hospData=   hospDataMapper.selectHospDataById(homeHospId);
+         HospData hospData = hospDataMapper.selectHospDataById(homeHospId);
          hospitals.add(0,hospData);
         }
         return success(hospitals);
     }
     
     /**
-     * 鏍规嵁閮ㄩ棬鍖哄煙閰嶇疆鎼滅储鍖婚櫌锛堜粠MySQL tb_hosp_data琛ㄦ煡璇紝鏀寔鐪併�佸競銆佸幙/鍖虹瓑澶氱骇鍖哄煙锛�
+     * 鏍规嵁閮ㄩ棬鍖哄煙閰嶇疆鎼滅储鍖婚櫌锛堜粠MySQLtb_hosp_data琛ㄦ煡璇紝鏀寔鐪併�佸競銆佸幙/鍖虹瓑澶氱骇鍖哄煙锛�
      * @param keyword 鎼滅储鍏抽敭璇�
      * @param deptId 閮ㄩ棬ID
+     * @param pageSize 杩斿洖缁撴灉鏁伴噺闄愬埗锛堥粯璁�50锛�
      */
     @GetMapping("/search/by-dept-region")
     public AjaxResult searchHospitalsByDeptRegion(
             @RequestParam(value = "keyword", required = false) String keyword,
-            @RequestParam("deptId") Long deptId) {
-        logger.info("鏍规嵁閮ㄩ棬鍖哄煙閰嶇疆鎼滅储鍖婚櫌锛歞eptId={}, keyword={}", deptId, keyword);
+            @RequestParam("deptId") Long deptId,
+            @RequestParam(value = "pageSize", required = false, defaultValue = "50") Integer pageSize) {
+        logger.info("鏍规嵁閮ㄩ棬鍖哄煙閰嶇疆鎼滅储鍖婚櫌锛歞eptId={}, keyword={}, pageSize={}", deptId, keyword, pageSize);
         
         // 璋冪敤Mapper鏌ヨ锛岃嚜鍔ㄦ牴鎹儴闂ㄧ殑鍖哄煙閰嶇疆杩囨护鍖婚櫌
         List<HospData> hospitals = hospDataMapper.searchHospitalsByDeptRegion(keyword, deptId);
         logger.info("鏌ヨ鍒板尰闄㈡暟閲忥細{}", hospitals.size());
         
+        // 闄愬埗杩斿洖鏁伴噺
+        if (pageSize != null && pageSize > 0 && hospitals.size() > pageSize) {
+            hospitals = hospitals.subList(0, pageSize);
+        }
+        
         // 纭繚"瀹朵腑"鍦ㄧ粨鏋滀腑
         Integer homeHospId = hospDataMapper.getHomeHospId();
         if (homeHospId > 0 && hospitals.stream().noneMatch(h -> h.getHospId().equals(homeHospId))) {

--
Gitblit v1.9.1