Browse Source

【功能完善】商品列表,展示满减送、限时折扣的信息

YunaiV 11 months ago
parent
commit
b741a1d148
3 changed files with 164 additions and 52 deletions
  1. 18 16
      pages/goods/list.vue
  2. 3 3
      sheep/api/product/spu.js
  3. 143 33
      sheep/components/s-goods-column/s-goods-column.vue

+ 18 - 16
pages/goods/list.vue

@@ -118,7 +118,7 @@
 </template>
 
 <script setup>
-  import { reactive,ref } from 'vue';
+  import { reactive, ref } from 'vue';
   import { onLoad, onReachBottom } from '@dcloudio/uni-app';
   import sheep from '@/sheep';
   import _ from 'lodash-es';
@@ -278,13 +278,13 @@
       return;
     }
     // 使用 map 提取每个对象的 id 属性
-    const ids = data.list.map(item => item.id);
+    const ids = data.list.map((item) => item.id);
     // 使用 join 方法将 id 数组连接成一个用逗号分隔的字符串
     const idsString = ids.join(',');
     // 获取结算信息
-    settleData.value = await getSettlementByIds(idsString)
+    settleData.value = await getSettlementByIds(idsString);
     // 处理获得的数据
-    const ms = enrichDataWithSkus(data.list,settleData.value)
+    const ms = enrichDataWithSkus(data.list, settleData.value);
     state.pagination.list = _.concat(state.pagination.list, ms);
     state.pagination.total = data.total;
     state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
@@ -301,7 +301,7 @@
   }
 
   //获取结算信息
-  const settleData = ref()
+  const settleData = ref();
   async function getSettlementByIds(ids) {
     const { data } = await SpuApi.getSettlementProduct(ids);
     return data;
@@ -310,10 +310,10 @@
   //计算展示价格的函数
   function enrichDataWithSkus(data, array) {
     // 创建一个映射,以 id 为键,存储 data 数组中的对象
-    const dataMap = new Map(data.map(item => [item.id, { ...item }]));
+    const dataMap = new Map(data.map((item) => [item.id, { ...item }]));
 
     // 遍历 array 数组
-    array.forEach(item => {
+    array.forEach((item) => {
       // 初始化 discountPrice 和 vipPrice 为 null
       let discountPrice = null;
       let vipPrice = null;
@@ -321,13 +321,14 @@
       let foundType6 = false;
 
       // 遍历 skus 数组,寻找 type 为 4 和 6 的首个条目
-      item.skus.forEach(sku => {
-        if (!foundType4 && sku.type === 4) {
-          discountPrice = sku.price;
+      item.skus.forEach((sku) => {
+        debugger;
+        if (!foundType4 && sku.promotionType === 4) {
+          discountPrice = sku.payPrice;
           foundType4 = true;
         }
-        if (!foundType6 && sku.type === 6) {
-          vipPrice = sku.price;
+        if (!foundType6 && sku.promotionType === 6) {
+          vipPrice = sku.payPrice;
           foundType6 = true;
         }
 
@@ -338,10 +339,11 @@
       });
 
       // 更新 dataMap 中对应的对象
-      if (dataMap.has(item.id)) {
-        dataMap.get(item.id).discountPrice = discountPrice;
-        dataMap.get(item.id).vipPrice = vipPrice;
-        dataMap.get(item.id).reward = item.reward;
+      if (dataMap.has(item.spuId)) {
+        debugger;
+        dataMap.get(item.spuId).discountPrice = discountPrice;
+        dataMap.get(item.spuId).vipPrice = vipPrice;
+        dataMap.get(item.spuId).reward = item.rewardActivity;
       }
     });
 

+ 3 - 3
sheep/api/product/spu.js

@@ -14,11 +14,11 @@ const SpuApi = {
     });
   },
   // 获得商品结算信息
-  getSettlementProduct: (ids) => {
+  getSettlementProduct: (spuIds) => {
     return request({
-      url: '/trade/order/settlementProduct',
+      url: '/trade/order/settlement-product',
       method: 'GET',
-      params: { ids },
+      params: { spuIds },
       custom: {
         showLoading: false,
         showError: false,

+ 143 - 33
sheep/components/s-goods-column/s-goods-column.vue

@@ -27,13 +27,23 @@
         >
           {{ data.title || data.name }}
         </view>
+        <!-- 这里是新加的会员价和限时优惠 -->
+        <view class="iconBox" v-if="data.discountPrice || data.vipPrice || data.reward">
+          <view class="card" v-if="iconShow">{{ iconShow }}</view>
+          <view class="card2" v-if="data.reward">{{ data.reward.ruleDescriptions[0] }}</view>
+        </view>
+        <!-- 这里是新加的会员价和限时优惠结束 -->
         <view
           v-if="goodsFields.price?.show"
           class="xs-goods-price font-OPPOSANS"
           :style="[{ color: goodsFields.price.color }]"
         >
           <text class="price-unit ss-font-24">{{ priceUnit }}</text>
-          {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
+          <text v-if="iconShow == '限时优惠'">{{ fen2yuan(data.discountPrice) }}</text>
+          <text v-else-if="iconShow == '会员价'">{{ fen2yuan(data.vipPrice) }}</text>
+          <text v-else>{{
+            isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price)
+          }}</text>
         </view>
       </view>
     </view>
@@ -60,13 +70,23 @@
         >
           {{ data.title || data.name }}
         </view>
+        <!-- 这里是新加的会员价和限时优惠 -->
+        <view class="iconBox" v-if="data.discountPrice || data.vipPrice || data.reward">
+          <view class="card" v-if="iconShow">{{ iconShow }}</view>
+          <view class="card2" v-if="data.reward">{{ data.reward.ruleDescriptions[0] }}</view>
+        </view>
+        <!-- 这里是新加的会员价和限时优惠结束 -->
         <view
           v-if="goodsFields.price?.show"
           class="sm-goods-price font-OPPOSANS"
           :style="[{ color: goodsFields.price.color }]"
         >
           <text class="price-unit ss-font-24">{{ priceUnit }}</text>
-          {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
+          <text v-if="iconShow == '限时优惠'">{{ fen2yuan(data.discountPrice) }}</text>
+          <text v-else-if="iconShow == '会员价'">{{ fen2yuan(data.vipPrice) }}</text>
+          <text v-else>{{
+            isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price)
+          }}</text>
         </view>
       </view>
     </view>
@@ -110,6 +130,12 @@
             </view>
           </view>
         </slot>
+        <!-- 这里是新加的会员价和限时优惠 -->
+        <view class="iconBox" v-if="data.discountPrice || data.vipPrice || data.reward">
+          <view class="card" v-if="iconShow">{{ iconShow }}</view>
+          <view class="card2" v-if="data.reward">{{ data.reward.ruleDescriptions[0] }}</view>
+        </view>
+        <!-- 这里是新加的会员价和限时优惠结束 -->
         <view class="ss-flex ss-col-bottom">
           <view
             v-if="goodsFields.price?.show"
@@ -117,7 +143,11 @@
             :style="[{ color: goodsFields.price.color }]"
           >
             <text class="price-unit ss-font-24">{{ priceUnit }}</text>
-            {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
+            <text v-if="iconShow == '限时优惠'">{{ fen2yuan(data.discountPrice) }}</text>
+            <text v-else-if="iconShow == '会员价'">{{ fen2yuan(data.vipPrice) }}</text>
+            <text v-else>{{
+              isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price)
+            }}</text>
           </view>
 
           <view
@@ -189,6 +219,12 @@
               </view>
             </view>
           </slot>
+          <!-- 这里是新加的会员价和限时优惠 -->
+          <view class="iconBox" v-if="data.discountPrice || data.vipPrice || data.reward">
+            <view class="card" v-if="iconShow">{{ iconShow }}</view>
+            <view class="card2" v-if="data.reward">{{ data.reward.ruleDescriptions[0] }}</view>
+          </view>
+          <!-- 这里是新加的会员价和限时优惠结束 -->
           <view class="ss-flex ss-col-bottom ss-m-t-10">
             <view
               v-if="goodsFields.price?.show"
@@ -207,7 +243,11 @@
               :style="[{ color: originPriceColor }]"
             >
               <text class="price-unit ss-font-20">{{ priceUnit }}</text>
-              <view class="ss-m-l-8">{{ fen2yuan(data.marketPrice) }}</view>
+              <text v-if="iconShow == '限时优惠'">{{ fen2yuan(data.discountPrice) }}</text>
+              <text v-else-if="iconShow == '会员价'">{{ fen2yuan(data.vipPrice) }}</text>
+              <text v-else>{{
+                isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price)
+              }}</text>
             </view>
           </view>
           <view class="ss-m-t-8 ss-flex ss-col-center ss-flex-wrap">
@@ -262,10 +302,20 @@
               </view>
             </view>
           </slot>
+          <!-- 这里是新加的会员价和限时优惠 -->
+          <view class="iconBox" v-if="data.discountPrice || data.vipPrice || data.reward">
+            <view class="card" v-if="iconShow">{{ iconShow }}</view>
+            <view class="card2" v-if="data.reward">{{ data.reward.ruleDescriptions[0] }}</view>
+          </view>
+          <!-- 这里是新加的会员价和限时优惠结束 -->
           <view v-if="goodsFields.price?.show" class="ss-flex ss-col-bottom font-OPPOSANS">
             <view class="sl-goods-price ss-m-r-12" :style="[{ color: goodsFields.price.color }]">
               <text class="price-unit ss-font-24">{{ priceUnit }}</text>
-              {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
+              <text v-if="iconShow == '限时优惠'">{{ fen2yuan(data.discountPrice) }}</text>
+              <text v-else-if="iconShow == '会员价'">{{ fen2yuan(data.vipPrice) }}</text>
+              <text v-else>{{
+                isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price)
+              }}</text>
             </view>
             <view
               v-if="
@@ -297,36 +347,36 @@
    * 商品卡片
    *
    * @property {Array} size = [xs | sm | md | lg | sl ] 			 	- 列表数据
-   * @property {String} tag                      - md及以上才有
-   * @property {String} img                      - 图片
-   * @property {String} background                  - 背景色
-   * @property {String} topRadius                  - 上圆角
-   * @property {String} bottomRadius                  - 下圆角
-   * @property {String} title                    - 标题
-   * @property {String} titleColor                  - 标题颜色
+   * @property {String} tag 											- md及以上才有
+   * @property {String} img 											- 图片
+   * @property {String} background 									- 背景色
+   * @property {String} topRadius 									- 上圆角
+   * @property {String} bottomRadius 									- 下圆角
+   * @property {String} title 										- 标题
+   * @property {String} titleColor 									- 标题颜色
    * @property {Number} titleWidth = 0								- 标题宽度,默认0,单位rpx
-   * @property {String} subTitle                    - 副标题
-   * @property {String} subTitleColor                  - 副标题颜色
-   * @property {String} subTitleBackground              - 副标题背景
-   * @property {String | Number} price                - 价格
-   * @property {String} priceColor                  - 价格颜色
-   * @property {String | Number} originPrice              - 原价/划线价
-   * @property {String} originPriceColor                - 原价颜色
-   * @property {String | Number} sales                - 销售数量
-   * @property {String} salesColor                  - 销售数量颜色
+   * @property {String} subTitle 										- 副标题
+   * @property {String} subTitleColor									- 副标题颜色
+   * @property {String} subTitleBackground 							- 副标题背景
+   * @property {String | Number} price 								- 价格
+   * @property {String} priceColor 									- 价格颜色
+   * @property {String | Number} originPrice 							- 原价/划线价
+   * @property {String} originPriceColor 								- 原价颜色
+   * @property {String | Number} sales 								- 销售数量
+   * @property {String} salesColor									- 销售数量颜色
    *
    * @slots activity												 	- 活动插槽
    * @slots cart														- 购物车插槽,默认包含文字,背景色,文字颜色 || 图片 || 行为
    *
-   * @event {Function()} click                    - 点击卡片
+   * @event {Function()} click 										- 点击卡片
    *
    */
-  import { computed, reactive, getCurrentInstance, onMounted, nextTick } from 'vue';
+  import { computed, reactive, getCurrentInstance, onMounted, nextTick, ref } from 'vue';
   import sheep from '@/sheep';
   import { fen2yuan, formatSales } from '@/sheep/hooks/useGoods';
   import { formatStock } from '@/sheep/hooks/useGoods';
+  import goodsCollectVue from '@/pages/user/goods-collect.vue';
   import { isArray } from 'lodash-es';
-
   // 数据
   const state = reactive({});
 
@@ -337,17 +387,29 @@
       default() {
         return {
           // 商品价格
-          price: { show: true },
+          price: {
+            show: true,
+          },
           // 库存
-          stock: { show: true },
+          stock: {
+            show: true,
+          },
           // 商品名称
-          name: { show: true },
+          name: {
+            show: true,
+          },
           // 商品介绍
-          introduction: { show: true },
+          introduction: {
+            show: true,
+          },
           // 市场价
-          marketPrice: { show: true },
+          marketPrice: {
+            show: true,
+          },
           // 销量
-          salesCount: { show: true },
+          salesCount: {
+            show: true,
+          },
         };
       },
     },
@@ -416,7 +478,26 @@
       default: false,
     },
   });
-
+  //判断限时优惠和会员价标签内容暂时导致页面出错,又舍不得丢,等着把新的数据整合到商品信息中,也用起来
+  const iconShow = handle();
+
+  function handle() {
+    debugger;
+    if (props.data.discountPrice === null && props.data.vipPrice === null) {
+      // 如果两个值都为 null,则不展示任何内容
+      return '';
+    } else if (props.data.discountPrice === null) {
+      // 如果 discountPrice 为 null,展示 vipPrice
+      return '会员价';
+    } else if (props.data.vipPrice === null) {
+      // 如果 vipPrice 为 null,展示 discountPrice
+      return '限时优惠';
+    } else if (props.data.discountPrice < props.data.vipPrice) {
+      return '限时优惠';
+    } else if (props.data.discountPrice > props.data.vipPrice) {
+      return '会员价';
+    }
+  }
   // 组件样式
   const elStyles = computed(() => {
     return {
@@ -454,7 +535,10 @@
   function getGoodsPriceCardWH() {
     if (props.size === 'md') {
       const view = uni.createSelectorQuery().in(proxy);
-      view.select(`#${elId}`).fields({ size: true, scrollOffset: true });
+      view.select(`#${elId}`).fields({
+        size: true,
+        scrollOffset: true,
+      });
       view.exec((data) => {
         let totalHeight = 0;
         const goodsPriceCard = data[0];
@@ -469,7 +553,6 @@
       });
     }
   }
-
   onMounted(() => {
     nextTick(() => {
       getGoodsPriceCardWH();
@@ -763,4 +846,31 @@
       color: #ffffff;
     }
   }
+
+  .card {
+    width: fit-content;
+    height: fit-content;
+    padding: 2rpx 10rpx;
+    background-color: red;
+    color: #ffffff;
+    font-size: 24rpx;
+  }
+
+  .card2 {
+    width: fit-content;
+    height: fit-content;
+    padding: 2rpx 10rpx;
+    background-color: rgb(255, 242, 241);
+    color: #ff2621;
+    font-size: 24rpx;
+    margin-left: 5rpx;
+  }
+
+  .iconBox {
+    width: 100%;
+    height: fit-content;
+    margin-top: 10rpx;
+    display: flex;
+    justify-content: flex-start;
+  }
 </style>