Просмотр исходного кода

feat(health): 报告上传页关联商品卡片区(去重可购买)+ 成员4列核验

E2E Test Bot 6 дней назад
Родитель
Сommit
0bdc78def8
1 измененных файлов с 129 добавлено и 0 удалено
  1. 129 0
      cfc-frontend/pages/health/report-upload.vue

+ 129 - 0
cfc-frontend/pages/health/report-upload.vue

@@ -143,6 +143,29 @@
         <text class="guide-tips-item">· 确认入库后将自动生成成长方案,可再分解为每日任务</text>
       </view>
     </view>
+
+    <!-- 关联商品(后台配置的报告类型→商品;按商品 id 去重,点击可查看并购买) -->
+    <view class="linked-products-section" v-if="linkedProducts.length > 0">
+      <view class="linked-products-header">
+        <text class="linked-products-header-icon">🛒</text>
+        <text class="linked-products-title">关联商品</text>
+      </view>
+      <text class="linked-products-desc">以下商品与您的报告类型对应,点击可查看并购买</text>
+      <view class="linked-products-grid">
+        <view
+          class="linked-product-card"
+          v-for="(product, pIdx) in linkedProducts"
+          :key="getProductKey(product)"
+          hover-class="linked-product-hover"
+          @click="goProductDetailByProduct(product.productId)">
+          <view class="linked-product-info">
+            <text class="linked-product-name">{{ product.productName }}</text>
+            <text class="linked-product-tag">报告关联商品</text>
+          </view>
+          <view class="linked-product-btn">查看 / 购买</view>
+        </view>
+      </view>
+    </view>
   </view>
 </template>
 
@@ -175,6 +198,23 @@ export default {
   computed: {
     tipText: function() {
       return '上传报告后由系统自动识别类型并解析:菌群检测、素质测评 A2、体检报告等'
+    },
+    // 关联商品:遍历报告类型→商品链接配置,按商品 id(linkedProductId)去重(Set 语义),
+    // 多个报告类型关联同一商品时只展示一次;未配置/接口失败返回 [],页面静默隐藏卡片区
+    linkedProducts: function() {
+      var list = this.reportTypeLinks || []
+      var seen = {}
+      var result = []
+      for (var i = 0; i < list.length; i++) {
+        var link = list[i]
+        if (!link || !link.linkedProductId) continue
+        var pid = parseInt(link.linkedProductId)
+        if (!pid || isNaN(pid) || pid <= 0) continue
+        if (seen[pid]) continue
+        seen[pid] = true
+        result.push({ productId: pid, productName: link.productName || '' })
+      }
+      return result
     }
   },
   onLoad: function(options) {
@@ -268,6 +308,15 @@ if (options.type === 'a2' || options.reportKind === 'a2') {
       if (!link || !link.linkedProductId) return
       uni.navigateTo({ url: '/pages/discover-detail/product-detail/product-detail?id=' + link.linkedProductId })
     },
+    // 商品卡片 :key(按商品 id 唯一,避免多类型关联同商品时模板键冲突)
+    getProductKey: function(product) {
+      return 'lp' + (product && product.productId)
+    },
+    // 点击「关联商品」卡片 → 按商品 id 直接跳转商城商品详情页(详情页含购买/加购入口)
+    goProductDetailByProduct: function(productId) {
+      if (!productId) return
+      uni.navigateTo({ url: '/pages/discover-detail/product-detail/product-detail?id=' + productId })
+    },
     ensureMember: function() {
       if (this.memberId) return true
       uni.showToast({ title: '请先选择报告所属成员', icon: 'none' })
@@ -929,4 +978,84 @@ if (options.type === 'a2' || options.reportKind === 'a2') {
   display: block;
   line-height: 1.7;
 }
+
+/* 关联商品卡片区(视觉与 guide-section 一致) */
+.linked-products-section {
+  margin: 0 $uni-space-lg $uni-space-xl;
+  background: $app-surface;
+  border-radius: 24rpx;
+  padding: 28rpx 24rpx;
+  box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04);
+}
+.linked-products-header {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  margin-bottom: 8rpx;
+}
+.linked-products-header-icon {
+  font-size: calc(32rpx * var(--font-scale, 1));
+  margin-right: 12rpx;
+}
+.linked-products-title {
+  font-size: calc(28rpx * var(--font-scale, 1));
+  font-weight: 600;
+  color: $uni-text-color;
+}
+.linked-products-desc {
+  font-size: calc(22rpx * var(--font-scale, 1));
+  color: $app-text-subtle;
+  line-height: 1.5;
+  display: block;
+  margin-bottom: 20rpx;
+}
+.linked-products-grid {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  gap: 16rpx;
+}
+.linked-product-card {
+  width: calc((100% - 16rpx) / 2);
+  display: flex;
+  flex-direction: column;
+  background: $app-bg;
+  border: 2rpx solid $facade-fill-slate;
+  border-radius: 16rpx;
+  padding: 20rpx 16rpx;
+}
+.linked-product-hover {
+  opacity: 0.85;
+}
+.linked-product-info {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  min-width: 0;
+}
+.linked-product-name {
+  font-size: calc(24rpx * var(--font-scale, 1));
+  font-weight: 600;
+  color: $facade-text-strong;
+  display: block;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  margin-bottom: 6rpx;
+}
+.linked-product-tag {
+  font-size: calc(20rpx * var(--font-scale, 1));
+  color: $app-text-subtle;
+}
+.linked-product-btn {
+  margin-top: 14rpx;
+  height: 56rpx;
+  line-height: 56rpx;
+  text-align: center;
+  background: $facade-brand-tint-2;
+  color: $facade-violet;
+  font-size: calc(24rpx * var(--font-scale, 1));
+  font-weight: 600;
+  border-radius: 12rpx;
+}
 </style>