Browse Source

团购详情页面修改

shizhongqi 15 hours ago
parent
commit
dc315e2770
1 changed files with 163 additions and 26 deletions
  1. 163 26
      mallApp/src/pages/groupBuy/detail.vue

+ 163 - 26
mallApp/src/pages/groupBuy/detail.vue

@@ -1,7 +1,7 @@
 <!--
   团购详情 / 开团入口页
   从首页团购专区点击进入(goodsId),或从分享卡片进入(id=groupBuyId)
-  展示商品信息、当前拼团卡片、开团玩法、底部开团/参团/分享操作
+  展示商品信息、活动规则(land.desc)、商品详情图文(picTextGoods)、开团玩法、底部操作
 -->
 <template>
   <view class="group-buy-detail-page">
@@ -36,7 +36,7 @@
         />
       </view>
       <text class="goods-name">{{ goods.name }}</text>
-      <text class="goods-desc">{{ goods.subtitle || goods.desc || '精选鲜花,拼团更优惠' }}</text>
+      <text class="goods-desc">{{ goods.subtitle || '精选鲜花,拼团更优惠' }}</text>
     </view>
 
     <!-- 当前拼团中卡片 -->
@@ -67,18 +67,35 @@
       </view>
     </view>
 
-    <!-- 商品详情图 -->
-    <view class="detail-section">
+    <!-- 团购活动说明:来自 getGoodsLanding 的 desc,按行拆成编号规则列表 -->
+    <view v-if="activityRules.length" class="rule-card">
+      <view class="rule-title-wrap">
+        <view class="rule-sparkle rule-sparkle-left"></view>
+        <text class="rule-title">活动规则</text>
+        <view class="rule-sparkle rule-sparkle-right"></view>
+      </view>
+      <view class="rule-list">
+        <view
+          v-for="(line, idx) in activityRules"
+          :key="idx"
+          class="rule-item"
+        >
+          <view class="rule-num">{{ idx + 1 }}</view>
+          <text class="rule-text">{{ line }}</text>
+        </view>
+      </view>
+    </view>
+
+    <!-- 商品详情卡片:与开团玩法同款白底圆角卡片,内容用 rich-media-viewer 渲染 -->
+    <view class="detail-card">
       <text class="detail-title">商品详情</text>
-      <image
-        v-for="(img, idx) in detailImages"
-        :key="idx"
-        class="detail-img"
-        :src="img"
-        mode="widthFix"
-      />
-      <view v-if="!detailImages.length" class="detail-empty">
-        <text>{{ goods.desc || '暂无更多详情' }}</text>
+      <view class="detail-content">
+        <rich-media-viewer
+          ref="richMediaViewerGoods"
+          :content="previewContent"
+          :startScroll="350"
+          :threshold="550"
+        />
       </view>
     </view>
 
@@ -119,6 +136,7 @@
 import { mapGetters } from 'vuex'
 import CountDown from '@/components/CountDown.vue'
 import GroupAvatarStack from '@/components/GroupAvatarStack.vue'
+import RichMediaViewer from '@/components/RichMediaViewer/index.vue'
 import wangCg from '@/components/wangCg'
 import share from '@/mixins/share'
 import {
@@ -131,7 +149,7 @@ import { GROUP_BUY_HD_NOT_BOUND } from '@/constant/errCode'
 
 export default {
   name: 'GroupBuyDetail',
-  components: { CountDown, GroupAvatarStack, wangCg },
+  components: { CountDown, GroupAvatarStack, RichMediaViewer, wangCg },
   mixins: [share],
   data() {
     return {
@@ -141,6 +159,8 @@ export default {
       goods: {},
       openGroup: null,
       detailImages: [],
+      // 商品详情图文块列表,结构与商品详情页 previewContent 一致
+      previewContent: [],
       swiperIndex: 0,
       remainText: '00:00:00',
       _remainTimer: null,
@@ -167,6 +187,18 @@ export default {
       })
       return list.length ? list : ['/static/images/user/attr-default.png']
     },
+    /**
+     * 活动说明按换行拆成规则条目;去掉行首自带序号,避免与粉色编号球重复
+     */
+    activityRules() {
+      const desc = (this.goods && this.goods.desc) || ''
+      if (!String(desc).trim()) return []
+      return String(desc)
+        .split(/\r?\n/)
+        .map((s) => s.trim())
+        .filter(Boolean)
+        .map((line) => line.replace(/^\d+[\.、\)]\s*/, ''))
+    },
     shareGroupId() {
       if (this.groupBuyId) return this.groupBuyId
       if (this.openGroup && this.openGroup.id) return this.openGroup.id
@@ -210,6 +242,14 @@ export default {
   onUnload() {
     this.clearRemainTimer()
   },
+  // 页面滚动时驱动详情图懒加载可见性检测(与商品详情页一致)
+  onPageScroll(e) {
+    if (this.$refs.richMediaViewerGoods) {
+      this.$refs.richMediaViewerGoods.triggerCheckVisibility(
+        parseInt(e.scrollTop)
+      )
+    }
+  },
   onShareAppMessage() {
     return this.buildSharePayload()
   },
@@ -306,15 +346,34 @@ export default {
         endTime: data.endTime,
         startTime: data.startTime,
         subtitle: data.subtitle,
-        desc: data.desc,
+        desc: data.desc, // 团购活动说明(活动规则卡片)
         title: data.title
       }
       this.detailImages = data.detailImages || []
+      // 解析商品详情图文,供 rich-media-viewer 使用(与 goods/detail 一致)
+      this.previewContent = this.parsePicTextContent(
+        data.picTextGoods && data.picTextGoods.content
+      )
       if (!keepOpenGroup || !this.openGroup) {
         this.openGroup = data.openGroup || null
       }
       this.startRemainTimer()
     },
+    /**
+     * 将接口返回的 picTextGoods.content 转为数组
+     * @param {string|Array} content JSON 字符串或已解析数组
+     * @returns {Array}
+     */
+    parsePicTextContent(content) {
+      if (!content) return []
+      if (Array.isArray(content)) return content
+      try {
+        const parsed = JSON.parse(content)
+        return Array.isArray(parsed) ? parsed : []
+      } catch (e) {
+        return []
+      }
+    },
     applyGroupDetail(data) {
       if (!data) return
       this.groupBuyId = data.id
@@ -698,25 +757,103 @@ export default {
   color: #999;
   text-align: center;
 }
-.detail-section {
-  margin-top: 20upx;
+/* 活动规则卡片:浅粉底 + 居中标题 + 全宽编号列表 */
+.rule-card {
+  margin: 20upx 24upx 0;
+  padding: 28upx 28upx 24upx;
+  border-radius: 16upx;
+  background: #fff;
+}
+.rule-title-wrap {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: center;
+}
+.rule-title {
+  font-size: 30upx;
+  font-weight: 600;
+  color: #333;
+  margin: 0 16upx;
+}
+.rule-sparkle {
+  width: 18upx;
+  height: 18upx;
+  position: relative;
+}
+.rule-sparkle::before,
+.rule-sparkle::after {
+  content: '';
+  position: absolute;
+  background: #ff8aa5;
+  border-radius: 2upx;
+}
+.rule-sparkle::before {
+  width: 16upx;
+  height: 4upx;
+  left: 1upx;
+  top: 7upx;
+  transform: rotate(-35deg);
+}
+.rule-sparkle::after {
+  width: 4upx;
+  height: 16upx;
+  left: 7upx;
+  top: 1upx;
+  transform: rotate(-35deg);
+}
+.rule-sparkle-right {
+  transform: scaleX(-1);
+}
+.rule-list {
+  margin-top: 24upx;
+}
+.rule-item {
+  display: flex;
+  flex-direction: row;
+  align-items: flex-start;
+  margin-top: 18upx;
+}
+.rule-item:first-child {
+  margin-top: 0;
+}
+.rule-num {
+  width: 36upx;
+  height: 36upx;
+  border-radius: 50%;
+  background: #ff8aa5;
+  color: #fff;
+  font-size: 22upx;
+  font-weight: 600;
+  text-align: center;
+  line-height: 36upx;
+  flex-shrink: 0;
+  margin-right: 16upx;
+  margin-top: 2upx;
+}
+.rule-text {
+  flex: 1;
+  font-size: 26upx;
+  color: #555;
+  line-height: 1.6;
+}
+/* 商品详情卡片:外边距/圆角/白底与 howto-card 保持一致 */
+.detail-card {
+  margin: 20upx 24upx 0;
   background: #fff;
-  padding: 28upx 0 40upx;
+  border-radius: 16upx;
+  padding: 28upx 20upx;
+  overflow: hidden;
 }
 .detail-title {
   display: block;
-  padding: 0 24upx 20upx;
   font-size: 30upx;
   font-weight: 600;
+  color: #222;
 }
-.detail-img {
+.detail-content {
   width: 100%;
-  display: block;
-}
-.detail-empty {
-  padding: 40upx 24upx;
-  color: #999;
-  font-size: 26upx;
+  margin-top: 20upx;
 }
 .foot-bar {
   position: fixed;