Forráskód Böngészése

优化药品比价的逻辑

yang yi 7 hónapja
szülő
commit
4d54df15f7
3 módosított fájl, 351 hozzáadás és 55 törlés
  1. 126 26
      pages/order/order.js
  2. 62 21
      pages/order/order.wxml
  3. 163 8
      pages/order/order.wxss

+ 126 - 26
pages/order/order.js

@@ -9,12 +9,15 @@ Page({
     hospitals: mockData.hospitals,
     filteredHospitals: mockData.hospitals,
     priceResults: [],
+    selectedMedicine: null,
     hotMedicines: [
       { name: '阿莫西林胶囊', minPrice: 24.8 },
       { name: '布洛芬缓释胶囊', minPrice: 17.5 },
       { name: '氯雷他定片', minPrice: 30.5 },
       { name: '奥美拉唑肠溶胶囊', minPrice: 45.0 }
     ],
+    otherMedicines: [],
+    selectedMedicineQuantity: {},
     showCaseModal: false,
     showMedicineModal: false,
     showPriceConfirmModal: false,
@@ -28,6 +31,27 @@ Page({
 
   onLoad() {
     console.log('下单页面加载完成')
+    this.loadOtherMedicines()
+  },
+
+  loadOtherMedicines() {
+    const hotMedicineNames = this.data.hotMedicines.map(m => m.name)
+    const otherMedicines = []
+    
+    for (const medicineName in mockData.medicinePrices) {
+      if (!hotMedicineNames.includes(medicineName)) {
+        const prices = mockData.medicinePrices[medicineName]
+        const minPrice = Math.min(...prices.map(p => p.price))
+        otherMedicines.push({
+          name: medicineName,
+          minPrice: minPrice
+        })
+      }
+    }
+    
+    this.setData({
+      otherMedicines: otherMedicines
+    })
   },
 
   // 切换选项卡
@@ -52,20 +76,36 @@ Page({
 
   // 药品搜索
   onMedicineSearch(e) {
-    const keyword = e.detail.value
+    const keyword = e.detail.value.trim()
     this.setData({
-      medicineKeyword: keyword
+      medicineKeyword: keyword,
+      selectedMedicine: null,
+      priceResults: []
     })
 
-    if (keyword && mockData.medicinePrices[keyword]) {
-      this.setData({
-        priceResults: mockData.medicinePrices[keyword]
-      })
-    } else {
-      this.setData({
-        priceResults: []
-      })
+    if (!keyword) {
+      // 清空搜索时,重新加载所有药品信息
+      this.loadOtherMedicines()
+      return
     }
+
+    // 模糊搜索:查找包含关键词的药品
+    const matchedMedicines = []
+    for (const medicineName in mockData.medicinePrices) {
+      if (medicineName.includes(keyword)) {
+        const prices = mockData.medicinePrices[medicineName]
+        const minPrice = Math.min(...prices.map(p => p.price))
+        matchedMedicines.push({
+          name: medicineName,
+          minPrice: minPrice
+        })
+      }
+    }
+
+    // 将搜索结果显示在药品信息模块中
+    this.setData({
+      otherMedicines: matchedMedicines
+    })
   },
 
   // 选择医院
@@ -246,12 +286,50 @@ Page({
     })
   },
 
+  // 选择药品
+  selectMedicine(e) {
+    const medicineName = e.currentTarget.dataset.medicine
+    this.setData({
+      selectedMedicine: medicineName
+    })
+    
+    if (mockData.medicinePrices[medicineName]) {
+      const priceResults = mockData.medicinePrices[medicineName].map(item => {
+        const hospital = this.data.hospitals.find(h => h.name === item.hospital)
+        return {
+          ...item,
+          distance: hospital ? hospital.distance : '未知'
+        }
+      })
+      this.setData({
+        priceResults: priceResults
+      })
+    }
+  },
+
   // 获取医院位置
   getHospitalLocation(hospitalName) {
     const locations = {
       '北京协和医院': { latitude: 39.9139, longitude: 116.3917 },
       '上海瑞金医院': { latitude: 31.2304, longitude: 121.4737 },
-      '广州中山医院': { latitude: 23.1291, longitude: 113.2644 }
+      '广州中山医院': { latitude: 23.1291, longitude: 113.2644 },
+      '北京大学第一医院': { latitude: 39.9289, longitude: 116.3883 },
+      '上海华山医院': { latitude: 31.2165, longitude: 121.4449 },
+      '广东省人民医院': { latitude: 23.1256, longitude: 113.2732 },
+      '北京301医院': { latitude: 39.9135, longitude: 116.2766 },
+      '上海仁济医院': { latitude: 31.2269, longitude: 121.4997 },
+      '广州南方医院': { latitude: 23.1825, longitude: 113.2767 },
+      '北京中日友好医院': { latitude: 39.9792, longitude: 116.4472 },
+      '上海长征医院': { latitude: 31.2317, longitude: 121.4708 },
+      '广东省中医院': { latitude: 23.1215, longitude: 113.2665 },
+      '北京天坛医院': { latitude: 39.8726, longitude: 116.4168 },
+      '上海第九人民医院': { latitude: 31.2304, longitude: 121.4851 },
+      '广州华侨医院': { latitude: 23.1358, longitude: 113.3245 },
+      '北京安贞医院': { latitude: 39.9432, longitude: 116.4134 },
+      '上海新华医院': { latitude: 31.2576, longitude: 121.5119 },
+      '广州医科大学附属第一医院': { latitude: 23.1258, longitude: 113.2587 },
+      '北京朝阳医院': { latitude: 39.9299, longitude: 116.4443 },
+      '上海第六人民医院': { latitude: 31.1884, longitude: 121.4367 }
     }
     return locations[hospitalName] || { latitude: 39.9042, longitude: 116.4074 }
   },
@@ -302,24 +380,18 @@ Page({
     }
   },
 
-  // 选择热门药品
-  selectHotMedicine(e) {
-    const medicineName = e.currentTarget.dataset.medicine
+  // 返回药品列表
+  backToMedicines() {
     this.setData({
-      medicineKeyword: medicineName
+      selectedMedicine: null,
+      priceResults: []
     })
-    
-    if (mockData.medicinePrices[medicineName]) {
-      this.setData({
-        priceResults: mockData.medicinePrices[medicineName]
-      })
-    }
   },
 
   // 通过价格选择医院
   selectByPrice(e) {
     const priceInfo = e.currentTarget.dataset.price
-    const medicineName = this.data.medicineKeyword
+    const medicineName = this.data.selectedMedicine
     
     // 显示确认模态框
     this.setData({
@@ -327,12 +399,37 @@ Page({
       selectedPriceItem: {
         medicine: medicineName,
         hospital: priceInfo.hospital,
-        price: priceInfo.price
+        price: priceInfo.price,
+        distance: priceInfo.distance
       },
       deliveryAddress: ''
     })
   },
 
+  // 增加比价药品数量
+  increasePriceQuantity(e) {
+    const hospital = e.currentTarget.dataset.hospital
+    const selectedMedicineQuantity = { ...this.data.selectedMedicineQuantity }
+    selectedMedicineQuantity[hospital] = (selectedMedicineQuantity[hospital] || 0) + 1
+    
+    this.setData({
+      selectedMedicineQuantity
+    })
+  },
+
+  // 减少比价药品数量
+  decreasePriceQuantity(e) {
+    const hospital = e.currentTarget.dataset.hospital
+    const selectedMedicineQuantity = { ...this.data.selectedMedicineQuantity }
+    if ((selectedMedicineQuantity[hospital] || 0) > 0) {
+      selectedMedicineQuantity[hospital] = selectedMedicineQuantity[hospital] - 1
+      
+      this.setData({
+        selectedMedicineQuantity
+      })
+    }
+  },
+
   // 关闭比价确认模态框
   closePriceConfirmModal() {
     this.setData({
@@ -354,6 +451,7 @@ Page({
     }
 
     const selectedPriceItem = this.data.selectedPriceItem
+    const quantity = this.data.selectedMedicineQuantity[selectedPriceItem.hospital] || 1
     
     // 根据医院生成地图轨迹数据
     const hospitalLocation = this.getHospitalLocation(selectedPriceItem.hospital)
@@ -364,7 +462,8 @@ Page({
       id: Date.now(),
       hospital: selectedPriceItem.hospital,
       medicines: [selectedPriceItem.medicine],
-      totalPrice: selectedPriceItem.price,
+      totalPrice: selectedPriceItem.price * quantity,
+      quantity: quantity,
       status: '配送中',
       date: new Date().toISOString().split('T')[0],
       deliveryAddress: this.data.deliveryAddress,
@@ -386,12 +485,13 @@ Page({
     this.setData({
       showPriceConfirmModal: false,
       selectedPriceItem: null,
-      deliveryAddress: ''
+      deliveryAddress: '',
+      selectedMedicineQuantity: {}
     })
 
     wx.showModal({
       title: '下单成功',
-      content: `订单总价:¥${selectedPriceItem.price}\n送货地址:${savedAddress}\n药品将尽快通过无人机配送`,
+      content: `订单总价:¥${selectedPriceItem.price * quantity}\n药品数量:${quantity}\n送货地址:${savedAddress}\n药品将尽快通过无人机配送`,
       showCancel: false,
       success: () => {
         // 跳转到我的页面查看订单

+ 62 - 21
pages/order/order.wxml

@@ -47,31 +47,13 @@
       </view>
     </view>
 
-    <!-- 药品比价结果 -->
-    <view class="price-comparison" wx:if="{{medicineKeyword}}">
-      <view class="medicine-title">
-        <text>药品:{{medicineKeyword}}</text>
-      </view>
-      <view class="price-list">
-        <view class="price-item" wx:for="{{priceResults}}" wx:key="hospital" bindtap="selectByPrice" data-price="{{item}}">
-          <view class="hospital-info">
-            <text class="hospital-name">{{item.hospital}}</text>
-            <text class="price">¥{{item.price}}</text>
-          </view>
-          <view class="action">
-            <text class="select-btn">选择</text>
-          </view>
-        </view>
-      </view>
-    </view>
-
     <!-- 热门药品推荐 -->
-    <view class="hot-medicines" wx:if="{{!medicineKeyword}}">
+    <view class="hot-medicines" wx:if="{{!selectedMedicine}}">
       <view class="section-title">
         <text>热门药品</text>
       </view>
       <view class="medicine-grid">
-        <view class="medicine-item" wx:for="{{hotMedicines}}" wx:key="name" bindtap="selectHotMedicine" data-medicine="{{item.name}}">
+        <view class="medicine-item" wx:for="{{hotMedicines}}" wx:key="name" bindtap="selectMedicine" data-medicine="{{item.name}}">
           <image class="medicine-icon" src="{{item.icon || '/images/medicine-default.png'}}" mode="aspectFit"></image>
           <view class="medicine-info">
             <text class="medicine-name">{{item.name}}</text>
@@ -80,6 +62,53 @@
         </view>
       </view>
     </view>
+
+    <!-- 药品信息 -->
+    <view class="other-medicines" wx:if="{{!selectedMedicine}}">
+      <view class="section-title">
+        <text>{{medicineKeyword ? '搜索结果' : '药品信息'}}</text>
+      </view>
+      <view class="medicine-list">
+        <view class="medicine-list-item" wx:for="{{otherMedicines}}" wx:key="name" bindtap="selectMedicine" data-medicine="{{item.name}}">
+          <view class="medicine-list-info">
+            <text class="medicine-list-name">{{item.name}}</text>
+            <text class="medicine-list-price">¥{{item.minPrice}}起</text>
+          </view>
+          <view class="medicine-list-arrow">
+            <text>></text>
+          </view>
+        </view>
+      </view>
+    </view>
+
+    <!-- 药品比价结果 -->
+    <view class="price-comparison" wx:if="{{selectedMedicine && priceResults.length > 0}}">
+      <view class="medicine-title">
+        <text class="back-btn" bindtap="backToMedicines">← 返回</text>
+        <text>药品:{{selectedMedicine}}</text>
+      </view>
+      <view class="price-list">
+        <view class="price-item" wx:for="{{priceResults}}" wx:key="hospital">
+          <view class="info-row">
+            <view class="hospital-info" bindtap="selectByPrice" data-price="{{item}}">
+              <text class="hospital-name">{{item.hospital}}</text>
+              <view class="price-info">
+                <text class="price">¥{{item.price}}</text>
+                <text class="distance">{{item.distance}}</text>
+              </view>
+            </view>
+            <view class="quantity-control" catchtap>
+              <text class="btn minus" bindtap="decreasePriceQuantity" data-hospital="{{item.hospital}}">-</text>
+              <text class="quantity">{{selectedMedicineQuantity[item.hospital] || 0}}</text>
+              <text class="btn plus" bindtap="increasePriceQuantity" data-hospital="{{item.hospital}}">+</text>
+            </view>
+          </view>
+          <view class="order-btn-wrapper">
+            <button class="order-btn" bindtap="selectByPrice" data-price="{{item}}" catchtap>下单</button>
+          </view>
+        </view>
+      </view>
+    </view>
   </view>
 
   <!-- 病例单选择模态框 -->
@@ -175,9 +204,21 @@
           <text class="confirm-value">{{selectedPriceItem.hospital}}</text>
         </view>
         <view class="confirm-item">
-          <text class="confirm-label">价格:</text>
+          <text class="confirm-label">距离:</text>
+          <text class="confirm-value">{{selectedPriceItem.distance}}</text>
+        </view>
+        <view class="confirm-item">
+          <text class="confirm-label">单价:</text>
           <text class="confirm-value price">¥{{selectedPriceItem.price}}</text>
         </view>
+        <view class="confirm-item">
+          <text class="confirm-label">数量:</text>
+          <text class="confirm-value">{{selectedMedicineQuantity[selectedPriceItem.hospital] || 1}}</text>
+        </view>
+        <view class="confirm-item">
+          <text class="confirm-label">总价:</text>
+          <text class="confirm-value price">¥{{selectedPriceItem.price * (selectedMedicineQuantity[selectedPriceItem.hospital] || 1)}}</text>
+        </view>
       </view>
       
       <!-- 送货地址 -->

+ 163 - 8
pages/order/order.wxss

@@ -151,6 +151,22 @@
   font-weight: bold;
   color: #333;
   box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
+  display: flex;
+  align-items: center;
+  gap: 20rpx;
+}
+
+.back-btn {
+  font-size: 26rpx;
+  color: #007AFF;
+  cursor: pointer;
+  padding: 5rpx 10rpx;
+  border-radius: 5rpx;
+  transition: background 0.3s;
+}
+
+.back-btn:active {
+  background: #e6f7ff;
 }
 
 .price-list {
@@ -162,8 +178,7 @@
 
 .price-item {
   display: flex;
-  justify-content: space-between;
-  align-items: center;
+  flex-direction: column;
   padding: 25rpx;
   border-bottom: 1rpx solid #f0f0f0;
   transition: background 0.3s;
@@ -177,9 +192,21 @@
   background: #f8f8f8;
 }
 
+.price-item .info-row {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 15rpx;
+}
+
 .price-item .hospital-info {
   display: flex;
   flex-direction: column;
+  flex: 1;
+}
+
+.price-item .hospital-info:active {
+  opacity: 0.7;
 }
 
 .price-item .hospital-name {
@@ -188,18 +215,81 @@
   margin-bottom: 8rpx;
 }
 
+.price-info {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
 .price {
   font-size: 32rpx;
   color: #FF6B35;
   font-weight: bold;
 }
 
-.select-btn {
+.price-item .distance {
+  font-size: 24rpx;
+  color: #007AFF;
+}
+
+.price-item .quantity-control {
+  display: flex;
+  align-items: center;
+  gap: 15rpx;
+  flex-shrink: 0;
+}
+
+.price-item .quantity-control .btn {
+  width: 50rpx;
+  height: 50rpx;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 32rpx;
+  font-weight: bold;
+}
+
+.price-item .quantity-control .minus {
+  background: #f0f0f0;
+  color: #666;
+}
+
+.price-item .quantity-control .plus {
   background: #007AFF;
   color: white;
-  padding: 12rpx 30rpx;
-  border-radius: 30rpx;
-  font-size: 24rpx;
+}
+
+.price-item .quantity {
+  font-size: 28rpx;
+  color: #333;
+  min-width: 40rpx;
+  text-align: center;
+}
+
+.price-item .order-btn-wrapper {
+  margin-top: 15rpx;
+  flex-shrink: 0;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.price-item .order-btn {
+  background: #007AFF;
+  color: white;
+  border: none;
+  border-radius: 4rpx;
+  padding: 6rpx 12rpx;
+  font-size: 20rpx;
+  line-height: 1;
+  min-width: 60rpx;
+  height: 40rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin: 0;
+  box-sizing: border-box;
 }
 
 .hot-medicines {
@@ -219,6 +309,8 @@
   display: flex;
   flex-wrap: wrap;
   gap: 20rpx;
+  width: 100%;
+  box-sizing: border-box;
 }
 
 .medicine-grid .medicine-item {
@@ -227,6 +319,8 @@
   border-radius: 15rpx;
   padding: 20rpx;
   box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
+  box-sizing: border-box;
+  flex-shrink: 0;
   display: flex;
   flex-direction: row;
   align-items: center;
@@ -265,6 +359,60 @@
   font-weight: bold;
 }
 
+.other-medicines {
+  padding: 20rpx;
+  margin-top: 20rpx;
+}
+
+.other-medicines .medicine-list {
+  background: white;
+  border-radius: 15rpx;
+  overflow: hidden;
+  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
+}
+
+.medicine-list-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 25rpx;
+  border-bottom: 1rpx solid #f0f0f0;
+  transition: background 0.3s;
+}
+
+.medicine-list-item:last-child {
+  border-bottom: none;
+}
+
+.medicine-list-item:active {
+  background: #f8f8f8;
+}
+
+.medicine-list-info {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+}
+
+.medicine-list-name {
+  font-size: 28rpx;
+  color: #333;
+  margin-bottom: 8rpx;
+}
+
+.medicine-list-price {
+  font-size: 24rpx;
+  color: #FF6B35;
+  font-weight: bold;
+}
+
+.medicine-list-arrow {
+  font-size: 32rpx;
+  color: #ccc;
+  margin-left: 15rpx;
+  flex-shrink: 0;
+}
+
 .modal {
   position: fixed;
   top: 0;
@@ -276,16 +424,23 @@
   align-items: center;
   justify-content: center;
   z-index: 1000;
+  overflow: auto;
+  padding: 20rpx;
+  flex-direction: row;
 }
 
 .modal-content {
   background: white;
   border-radius: 20rpx;
   width: 90%;
-  max-height: 80%;
-  overflow: hidden;
+  max-width: 600rpx;
+  max-height: 80vh;
+  overflow-y: auto;
   display: flex;
   flex-direction: column;
+  margin: auto;
+  align-self: center;
+  align-items: stretch;
 }
 
 .modal-header {