ソースを参照

feat: add purchase recommendation section to dan-assessment/report-upload page

Xiaogang Liao 2 ヶ月 前
コミット
5e8c708336
1 ファイル変更138 行追加4 行削除
  1. 138 4
      cfc-frontend/pages/dan-assessment/report-upload.vue

+ 138 - 4
cfc-frontend/pages/dan-assessment/report-upload.vue

@@ -15,17 +15,40 @@
         <view class="dimension-options">
           <view
             :class="['dimension-option', dimension === 'mind' ? 'active' : '']"
-            @click="dimension = 'mind'">
+            @click="selectDimension('mind')">
             <text class="dimension-name">&#x2764; 心维度 (A2)</text>
           </view>
           <view
             :class="['dimension-option', dimension === 'wisdom' ? 'active' : '']"
-            @click="dimension = 'wisdom'">
+            @click="selectDimension('wisdom')">
             <text class="dimension-name">&#x1F9E0; 智维度 (B4)</text>
           </view>
         </view>
       </view>
 
+      <!-- 购买推荐 -->
+      <view class="purchase-section" v-if="recommendedProducts.length > 0">
+        <view class="purchase-header">
+          <text class="purchase-icon">📦</text>
+          <text class="purchase-title">为家人购买检测服务</text>
+        </view>
+        <scroll-view class="purchase-scroll" scroll-x enable-flex show-scrollbar="false">
+          <view
+            class="purchase-card"
+            v-for="item in recommendedProducts"
+            :key="item.id"
+            @click="goToProduct(item.id)"
+          >
+            <image class="purchase-cover" :src="item.coverImage || '/static/default-product.png'" mode="aspectFill" />
+            <text class="purchase-name">{{ item.name }}</text>
+            <text class="purchase-price">{{ formatPriceWithSymbol(item.price) }}</text>
+            <view class="purchase-btn">
+              <text class="purchase-btn-text">去购买</text>
+            </view>
+          </view>
+        </scroll-view>
+      </view>
+
       <view class="upload-area" @click="chooseFile">
         <view class="upload-icon" v-if="!selectedFile">&#x1F4C4;</view>
         <view class="upload-icon" v-else>&#x2705;</view>
@@ -117,7 +140,12 @@
 </template>
 
 <script>
-import { danParsePreview, danConfirmReport } from '../../utils/api.js'
+import { danParsePreview, danConfirmReport, productList } from '../../utils/api.js'
+
+var REPORT_DOMAIN_MAP = {
+  mind: 'mind',
+  wisdom: 'wisdom'
+}
 
 export default {
   data() {
@@ -128,9 +156,14 @@ export default {
       previewData: null,
       draftId: null,
       loading: false,
-      confirming: false
+      confirming: false,
+      recommendedProducts: [],
+      loadingProducts: false
     }
   },
+  onLoad: function() {
+    this.loadRecommendProducts(this.dimension)
+  },
   methods: {
     goBack: function() {
       uni.navigateBack()
@@ -215,6 +248,37 @@ export default {
       this.selectedFile = null
       this.previewData = null
       this.draftId = null
+    },
+    selectDimension: function(dim) {
+      this.dimension = dim
+      this.loadRecommendProducts(dim)
+    },
+    loadRecommendProducts: function(dimension) {
+      var domain = REPORT_DOMAIN_MAP[dimension]
+      if (!domain) {
+        this.recommendedProducts = []
+        return
+      }
+      var self = this
+      self.loadingProducts = true
+      productList({ domain: domain, productType: 'assessment', size: 4 }).then(function(res) {
+        if (res && res.data && res.data.records) {
+          self.recommendedProducts = res.data.records
+        } else {
+          self.recommendedProducts = []
+        }
+      }).catch(function() {
+        self.recommendedProducts = []
+      }).finally(function() {
+        self.loadingProducts = false
+      })
+    },
+    goToProduct: function(productId) {
+      uni.navigateTo({ url: '/pages/discover/product-detail/product-detail?id=' + productId })
+    },
+    formatPriceWithSymbol: function(cents) {
+      if (cents === null || cents === undefined) return '¥0'
+      return '¥' + (cents / 100).toFixed(2)
     }
   }
 }
@@ -502,4 +566,74 @@ export default {
   font-size: 30rpx;
   color: #333;
 }
+.purchase-section {
+  background: #F0F9FF;
+  border-radius: 16rpx;
+  padding: 24rpx;
+  margin-top: 24rpx;
+  border: 2rpx solid #BAE6FD;
+}
+.purchase-header {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  margin-bottom: 16rpx;
+}
+.purchase-icon {
+  font-size: 28rpx;
+  margin-right: 8rpx;
+}
+.purchase-title {
+  font-size: 26rpx;
+  font-weight: bold;
+  color: #0369A1;
+}
+.purchase-scroll {
+  display: flex;
+  flex-direction: row;
+  white-space: nowrap;
+}
+.purchase-card {
+  display: inline-flex;
+  flex-direction: column;
+  width: 220rpx;
+  background: #fff;
+  border-radius: 12rpx;
+  padding: 16rpx;
+  margin-right: 16rpx;
+  flex-shrink: 0;
+}
+.purchase-cover {
+  width: 188rpx;
+  height: 120rpx;
+  border-radius: 8rpx;
+  background: #F1F5F9;
+  margin-bottom: 8rpx;
+}
+.purchase-name {
+  font-size: 22rpx;
+  color: #333;
+  line-height: 1.3;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  margin-bottom: 4rpx;
+}
+.purchase-price {
+  font-size: 24rpx;
+  color: #EF4444;
+  font-weight: bold;
+  margin-bottom: 8rpx;
+}
+.purchase-btn {
+  background: #3B82F6;
+  border-radius: 8rpx;
+  padding: 8rpx 0;
+  text-align: center;
+}
+.purchase-btn-text {
+  font-size: 22rpx;
+  color: #fff;
+  font-weight: 500;
+}
 </style>