Browse Source

【功能完善】商品详情,增加满减送提示

YunaiV 11 months ago
parent
commit
9df0194aeb

+ 53 - 57
pages/activity/index.vue

@@ -7,7 +7,7 @@
         <view class="type-text ss-flex ss-row-center">满减:</view>
         <view class="type-text ss-flex ss-row-center">满减:</view>
         <view class="ss-flex-1">
         <view class="ss-flex-1">
           <view class="tip-content" v-for="item in state.activityInfo.rules" :key="item">
           <view class="tip-content" v-for="item in state.activityInfo.rules" :key="item">
-            {{ formatRewardActivityRule(state.activityInfo, item) }}
+            {{ item.description }}
           </view>
           </view>
         </view>
         </view>
         <image class="activity-left-image" src="/static/activity-left.png" />
         <image class="activity-left-image" src="/static/activity-left.png" />
@@ -19,9 +19,13 @@
     <view class="ss-flex ss-flex-wrap ss-p-x-20 ss-m-t-20 ss-col-top">
     <view class="ss-flex ss-flex-wrap ss-p-x-20 ss-m-t-20 ss-col-top">
       <view class="goods-list-box">
       <view class="goods-list-box">
         <view class="left-list" v-for="item in state.leftGoodsList" :key="item.id">
         <view class="left-list" v-for="item in state.leftGoodsList" :key="item.id">
-          <s-goods-column class="goods-md-box" size="md" :data="item"
-                          @click="sheep.$router.go('/pages/goods/index', { id: item.id })"
-                          @getHeight="mountMasonry($event, 'left')">
+          <s-goods-column
+            class="goods-md-box"
+            size="md"
+            :data="item"
+            @click="sheep.$router.go('/pages/goods/index', { id: item.id })"
+            @getHeight="mountMasonry($event, 'left')"
+          >
             <template v-slot:cart>
             <template v-slot:cart>
               <button class="ss-reset-button cart-btn"> </button>
               <button class="ss-reset-button cart-btn"> </button>
             </template>
             </template>
@@ -30,9 +34,13 @@
       </view>
       </view>
       <view class="goods-list-box">
       <view class="goods-list-box">
         <view class="right-list" v-for="item in state.rightGoodsList" :key="item.id">
         <view class="right-list" v-for="item in state.rightGoodsList" :key="item.id">
-          <s-goods-column class="goods-md-box" size="md" :data="item"
-                          @click="sheep.$router.go('/pages/goods/index', { id: item.id })"
-                          @getHeight="mountMasonry($event, 'right')">
+          <s-goods-column
+            class="goods-md-box"
+            size="md"
+            :data="item"
+            @click="sheep.$router.go('/pages/goods/index', { id: item.id })"
+            @getHeight="mountMasonry($event, 'right')"
+          >
             <template v-slot:cart>
             <template v-slot:cart>
               <button class="ss-reset-button cart-btn" />
               <button class="ss-reset-button cart-btn" />
             </template>
             </template>
@@ -41,27 +49,22 @@
       </view>
       </view>
     </view>
     </view>
 
 
-    <uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" :content-text="{
+    <uni-load-more
+      v-if="state.pagination.total > 0"
+      :status="state.loadStatus"
+      :content-text="{
         contentdown: '上拉加载更多',
         contentdown: '上拉加载更多',
-      }" @tap="loadMore" />
+      }"
+      @tap="loadMore"
+    />
   </s-layout>
   </s-layout>
 </template>
 </template>
 <script setup>
 <script setup>
-  import {
-    reactive,
-    toRaw,
-    ref
-  } from 'vue';
-  import {
-    onLoad,
-    onReachBottom
-  } from '@dcloudio/uni-app';
+  import { reactive, toRaw, ref } from 'vue';
+  import { onLoad, onReachBottom } from '@dcloudio/uni-app';
   import sheep from '@/sheep';
   import sheep from '@/sheep';
   import _ from 'lodash-es';
   import _ from 'lodash-es';
   import RewardActivityApi from '@/sheep/api/promotion/rewardActivity';
   import RewardActivityApi from '@/sheep/api/promotion/rewardActivity';
-  import {
-    formatRewardActivityRule
-  } from '@/sheep/hooks/useGoods';
   import SpuApi from '@/sheep/api/product/spu';
   import SpuApi from '@/sheep/api/product/spu';
 
 
   const state = reactive({
   const state = reactive({
@@ -104,35 +107,31 @@
   async function getList() {
   async function getList() {
     // state.loadStatus = 'loading';
     // state.loadStatus = 'loading';
     // 处理拓展参数
     // 处理拓展参数
-    const params = {}
+    const params = {};
     if (state.activityInfo.productScope === 2) {
     if (state.activityInfo.productScope === 2) {
       // const params = toRaw(state.activityInfo.productScopeValues)
       // const params = toRaw(state.activityInfo.productScopeValues)
       // 请求数据
       // 请求数据
-      const {
-        code,
-        data
-      } = await SpuApi.getSpuListByIds(state.activityInfo.productScopeValues.join(','));
+      const { code, data } = await SpuApi.getSpuListByIds(
+        state.activityInfo.productScopeValues.join(','),
+      );
       if (code !== 0) {
       if (code !== 0) {
         return;
         return;
       }
       }
       // 使用 map 提取每个对象的 id 属性
       // 使用 map 提取每个对象的 id 属性
-      const ids = data.map(item => item.id);
+      const ids = data.map((item) => item.id);
       // 使用 join 方法将 id 数组连接成一个用逗号分隔的字符串
       // 使用 join 方法将 id 数组连接成一个用逗号分隔的字符串
       const idsString = ids.join(',');
       const idsString = ids.join(',');
       // 获取结算信息
       // 获取结算信息
-      settleData.value = await getSettlementByIds(idsString)
+      settleData.value = await getSettlementByIds(idsString);
       // 处理获得的数据
       // 处理获得的数据
-      const ms = enrichDataWithSkus(data, settleData.value)
+      const ms = enrichDataWithSkus(data, settleData.value);
       state.pagination.list = ms;
       state.pagination.list = ms;
       // state.pagination.total = data.total;
       // state.pagination.total = data.total;
       // state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
       // state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
     } else if (state.activityInfo.productScope === 3) {
     } else if (state.activityInfo.productScope === 3) {
       params.categoryIds = state.activityInfo.productScopeValues.join(',');
       params.categoryIds = state.activityInfo.productScopeValues.join(',');
       state.loadStatus = 'loading';
       state.loadStatus = 'loading';
-      const {
-        code,
-        data
-      } = await SpuApi.getSpuPage({
+      const { code, data } = await SpuApi.getSpuPage({
         pageNo: state.pagination.pageNo,
         pageNo: state.pagination.pageNo,
         pageSize: state.pagination.pageSize,
         pageSize: state.pagination.pageSize,
         ...params,
         ...params,
@@ -141,22 +140,19 @@
         return;
         return;
       }
       }
       // 使用 map 提取每个对象的 id 属性
       // 使用 map 提取每个对象的 id 属性
-      const ids = data.list.map(item => item.id);
+      const ids = data.list.map((item) => item.id);
       // 使用 join 方法将 id 数组连接成一个用逗号分隔的字符串
       // 使用 join 方法将 id 数组连接成一个用逗号分隔的字符串
       const idsString = ids.join(',');
       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.list = _.concat(state.pagination.list, ms);
       state.pagination.total = data.total;
       state.pagination.total = data.total;
       state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
       state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
     } else {
     } else {
       state.loadStatus = 'loading';
       state.loadStatus = 'loading';
-      const {
-        code,
-        data
-      } = await SpuApi.getSpuPage({
+      const { code, data } = await SpuApi.getSpuPage({
         pageNo: state.pagination.pageNo,
         pageNo: state.pagination.pageNo,
         pageSize: state.pagination.pageSize,
         pageSize: state.pagination.pageSize,
       });
       });
@@ -164,13 +160,13 @@
         return;
         return;
       }
       }
       // 使用 map 提取每个对象的 id 属性
       // 使用 map 提取每个对象的 id 属性
-      const ids = data.list.map(item => item.id);
+      const ids = data.list.map((item) => item.id);
       // 使用 join 方法将 id 数组连接成一个用逗号分隔的字符串
       // 使用 join 方法将 id 数组连接成一个用逗号分隔的字符串
       const idsString = ids.join(',');
       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.list = _.concat(state.pagination.list, ms);
       state.pagination.total = data.total;
       state.pagination.total = data.total;
       state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
       state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
@@ -178,22 +174,25 @@
     mountMasonry();
     mountMasonry();
   }
   }
   //获取结算信息
   //获取结算信息
-  const settleData = ref()
+  const settleData = ref();
   async function getSettlementByIds(ids) {
   async function getSettlementByIds(ids) {
-    const {
-      data
-    } = await SpuApi.getSettlementProduct(ids);
+    const { data } = await SpuApi.getSettlementProduct(ids);
     return data;
     return data;
   }
   }
   //计算展示价格的函数
   //计算展示价格的函数
   function enrichDataWithSkus(data, array) {
   function enrichDataWithSkus(data, array) {
     // 创建一个映射,以 id 为键,存储 data 数组中的对象
     // 创建一个映射,以 id 为键,存储 data 数组中的对象
-    const dataMap = new Map(data.map(item => [item.id, {
-      ...item
-    }]));
+    const dataMap = new Map(
+      data.map((item) => [
+        item.id,
+        {
+          ...item,
+        },
+      ]),
+    );
 
 
     // 遍历 array 数组
     // 遍历 array 数组
-    array.forEach(item => {
+    array.forEach((item) => {
       // 初始化 discountPrice 和 vipPrice 为 null
       // 初始化 discountPrice 和 vipPrice 为 null
       let discountPrice = null;
       let discountPrice = null;
       let vipPrice = null;
       let vipPrice = null;
@@ -201,7 +200,7 @@
       let foundType6 = false;
       let foundType6 = false;
 
 
       // 遍历 skus 数组,寻找 type 为 4 和 6 的首个条目
       // 遍历 skus 数组,寻找 type 为 4 和 6 的首个条目
-      item.skus.forEach(sku => {
+      item.skus.forEach((sku) => {
         if (!foundType4 && sku.type === 4) {
         if (!foundType4 && sku.type === 4) {
           discountPrice = sku.price;
           discountPrice = sku.price;
           foundType4 = true;
           foundType4 = true;
@@ -230,10 +229,7 @@
   }
   }
   // 加载活动信息
   // 加载活动信息
   async function getActivity(id) {
   async function getActivity(id) {
-    const {
-      code,
-      data
-    } = await RewardActivityApi.getRewardActivity(id);
+    const { code, data } = await RewardActivityApi.getRewardActivity(id);
     if (code === 0) {
     if (code === 0) {
       state.activityInfo = data;
       state.activityInfo = data;
     }
     }
@@ -312,4 +308,4 @@
       line-height: 42rpx;
       line-height: 42rpx;
     }
     }
   }
   }
-</style>
+</style>

+ 218 - 29
pages/goods/index.vue

@@ -27,10 +27,55 @@
             dotCur="bg-mask-40"
             dotCur="bg-mask-40"
             :seizeHeight="750"
             :seizeHeight="750"
           />
           />
-
+          <!-- 限时折扣/会员价的优惠信息 -->
+          <view class="discount" v-if="state.settlementSku && state.settlementSku.id">
+            <image class="disImg" :src="sheep.$url.static('/static/img/shop/goods/dis.png')" />
+            <view class="discountCont">
+              <view class="disContT">
+                <view class="disContT1">
+                  <view class="disContT1P">
+                    ¥{{ fen2yuan(state.settlementSku.promotionPrice) }}
+                  </view>
+                  <view class="disContT1End">
+                    直降¥
+                    {{ fen2yuan(state.settlementSku.price - state.settlementSku.promotionPrice) }}
+                  </view>
+                </view>
+                <view class="disContT2" v-if="state.settlementSku.promotionType === 4">
+                  限时折扣
+                </view>
+                <view class="disContT2" v-else-if="state.settlementSku.promotionType === 6">
+                  会员折扣
+                </view>
+              </view>
+              <view class="disContB">
+                <view class="disContB1">
+                  价格:¥{{ fen2yuan(state.settlementSku.price) }} 丨 剩余:
+                  {{ state.settlementSku.stock }}
+                </view>
+                <view class="disContB2" v-if="state.settlementSku.promotionEndTime > 0">
+                  距结束仅剩
+                  <countDown
+                    :tipText="' '"
+                    :bgColor="bgColor"
+                    :dayText="':'"
+                    :hourText="':'"
+                    :minuteText="':'"
+                    :secondText="' '"
+                    :datatime="state.settlementSku.promotionEndTime / 1000"
+                    :isDay="false"
+                  />
+                </view>
+              </view>
+            </view>
+          </view>
           <!-- 价格+标题 -->
           <!-- 价格+标题 -->
-          <view class="title-card detail-card ss-p-y-40 ss-p-x-20">
-            <view class="ss-flex ss-row-between ss-col-center ss-m-b-26">
+          <view class="title-card detail-card ss-p-y-30 ss-p-x-20">
+            <!-- 没有限时折扣/会员价的优惠信息时,展示的价格信息 -->
+            <view
+              class="ss-flex ss-row-between ss-col-center ss-m-b-26"
+              v-if="!(state.settlementSku && state.settlementSku.id)"
+            >
               <view class="price-box ss-flex ss-col-bottom">
               <view class="price-box ss-flex ss-col-bottom">
                 <view class="price-text ss-m-r-16">
                 <view class="price-text ss-m-r-16">
                   {{ fen2yuan(state.selectedSku.price || state.goodsInfo.price) }}
                   {{ fen2yuan(state.selectedSku.price || state.goodsInfo.price) }}
@@ -44,24 +89,37 @@
               </view>
               </view>
             </view>
             </view>
             <view class="discounts-box ss-flex ss-row-between ss-m-b-28">
             <view class="discounts-box ss-flex ss-row-between ss-m-b-28">
-              <!-- 满减送/限时折扣活动的提示 -->
+              <!-- 查看满减送的描述 -->
               <div class="tag-content">
               <div class="tag-content">
                 <view class="tag-box ss-flex">
                 <view class="tag-box ss-flex">
                   <view
                   <view
                     class="tag ss-m-r-10"
                     class="tag ss-m-r-10"
-                    v-for="promos in state.activityInfo"
+                    v-for="coupon in state.couponInfo.slice(0, 1)"
+                    :key="coupon.id"
+                    @tap="onOpenActivity"
+                  >
+                    [劵]满 {{ fen2yuan(coupon.usePrice) }} 元
+                    {{
+                      coupon.discountType === 1
+                        ? '减 ' + fen2yuan(coupon.discountPrice) + ' 元'
+                        : '打 ' + coupon.discountPercent / 10.0 + ' 折'
+                    }}
+                  </view>
+                  <view
+                    v-if="state.rewardActivity && state.rewardActivity.id > 0"
+                    class="tag ss-m-r-10"
+                    v-for="promos in state.rewardActivity.ruleDescriptions.slice(0, 1)"
                     :key="promos.id"
                     :key="promos.id"
-                    @tap="onActivity"
+                    @tap="onOpenActivity"
                   >
                   >
-                    {{ promos.name }}
+                    {{ promos }}
                   </view>
                   </view>
                 </view>
                 </view>
               </div>
               </div>
-
-              <!-- 优惠劵 -->
+              <!-- 领取优惠劵的按钮 -->
               <view
               <view
                 class="get-coupon-box ss-flex ss-col-center ss-m-l-20"
                 class="get-coupon-box ss-flex ss-col-center ss-m-l-20"
-                @tap="state.showModel = true"
+                @tap="onOpenActivity"
                 v-if="state.couponInfo.length"
                 v-if="state.couponInfo.length"
               >
               >
                 <view class="discounts-title ss-m-r-8">领券</view>
                 <view class="discounts-title ss-m-r-8">领券</view>
@@ -127,19 +185,12 @@
           </view>
           </view>
         </detail-tabbar>
         </detail-tabbar>
 
 
-        <!-- 优惠劵弹窗 -->
-        <s-coupon-get
-          v-model="state.couponInfo"
-          :show="state.showModel"
-          @close="state.showModel = false"
-          @get="onGet"
-        />
-
         <!-- 满减送/限时折扣活动弹窗 -->
         <!-- 满减送/限时折扣活动弹窗 -->
         <s-activity-pop
         <s-activity-pop
-          v-model="state.activityInfo"
+          v-model="state"
           :show="state.showActivityModel"
           :show="state.showActivityModel"
           @close="state.showActivityModel = false"
           @close="state.showActivityModel = false"
+          @get="onTakeCoupon"
         />
         />
       </block>
       </block>
     </s-layout>
     </s-layout>
@@ -147,7 +198,7 @@
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-  import { reactive, computed } from 'vue';
+  import { reactive, computed, ref } from 'vue';
   import { onLoad, onPageScroll } from '@dcloudio/uni-app';
   import { onLoad, onPageScroll } from '@dcloudio/uni-app';
   import sheep from '@/sheep';
   import sheep from '@/sheep';
   import CouponApi from '@/sheep/api/promotion/coupon';
   import CouponApi from '@/sheep/api/promotion/coupon';
@@ -165,7 +216,15 @@
   import SpuApi from '@/sheep/api/product/spu';
   import SpuApi from '@/sheep/api/product/spu';
 
 
   onPageScroll(() => {});
   onPageScroll(() => {});
-
+  import countDown from '@/sheep/components/countDown/index.vue';
+
+  const bgColor = {
+    bgColor: '#E93323',
+    Color: '#fff',
+    width: '44rpx',
+    timeTxtwidth: '16rpx',
+    isDay: true,
+  };
   const isLogin = computed(() => sheep.$store('user').isLogin);
   const isLogin = computed(() => sheep.$store('user').isLogin);
   const state = reactive({
   const state = reactive({
     goodsId: 0,
     goodsId: 0,
@@ -173,16 +232,18 @@
     goodsInfo: {}, // SPU 信息
     goodsInfo: {}, // SPU 信息
     showSelectSku: false, // 是否展示 SKU 选择弹窗
     showSelectSku: false, // 是否展示 SKU 选择弹窗
     selectedSku: {}, // 选中的 SKU
     selectedSku: {}, // 选中的 SKU
+    settlementSku: {}, // 结算的 SKU:由于 selectedSku 不进行默认选中,所以初始使用结算价格最低的 SKU 作为基础展示
     showModel: false, // 是否展示 Coupon 优惠劵的弹窗
     showModel: false, // 是否展示 Coupon 优惠劵的弹窗
     couponInfo: [], // 可领取的 Coupon 优惠劵的列表
     couponInfo: [], // 可领取的 Coupon 优惠劵的列表
     showActivityModel: false, // 【满减送/限时折扣】是否展示 Activity 营销活动的弹窗
     showActivityModel: false, // 【满减送/限时折扣】是否展示 Activity 营销活动的弹窗
-    activityInfo: [], // 【满减送/限时折扣】可参与的 Activity 营销活动的列表 TODO 芋艿:正在接入中
+    rewardActivity: {}, // 【满减送】活动
     activityList: [], // 【秒杀/拼团/砍价】可参与的 Activity 营销活动的列表
     activityList: [], // 【秒杀/拼团/砍价】可参与的 Activity 营销活动的列表
   });
   });
 
 
   // 规格变更
   // 规格变更
   function onSkuChange(e) {
   function onSkuChange(e) {
     state.selectedSku = e;
     state.selectedSku = e;
+    state.settlementSku = e;
   }
   }
 
 
   // 添加购物车
   // 添加购物车
@@ -196,7 +257,7 @@
 
 
   // 立即购买
   // 立即购买
   function onBuy(e) {
   function onBuy(e) {
-    if (!state.selectedSku.id) {
+    if (!e.id) {
       sheep.$helper.toast('请选择商品规格');
       sheep.$helper.toast('请选择商品规格');
       return;
       return;
     }
     }
@@ -213,13 +274,13 @@
     });
     });
   }
   }
 
 
-  // 营销活动
-  function onActivity() {
+  // 打开营销弹窗
+  function onOpenActivity() {
     state.showActivityModel = true;
     state.showActivityModel = true;
   }
   }
 
 
-  // 立即领取
-  async function onGet(id) {
+  // 立即领取优惠劵
+  async function onTakeCoupon(id) {
     const { code } = await CouponApi.takeCoupon(id);
     const { code } = await CouponApi.takeCoupon(id);
     if (code !== 0) {
     if (code !== 0) {
       return;
       return;
@@ -261,6 +322,36 @@
     }
     }
   }
   }
 
 
+  async function getSettlementByIds(ids) {
+    let { data, code } = await SpuApi.getSettlementProduct(ids);
+    if (code !== 0 || data.length !== 1) {
+      return;
+    }
+    data = data[0];
+
+    // 补充 SKU 的价格信息
+    state.goodsInfo.skus.forEach((sku) => {
+      data.skus.forEach((item) => {
+        if (sku.id === item.id) {
+          sku.promotionType = item.promotionType;
+          sku.promotionPrice = item.promotionPrice;
+          sku.promotionId = item.promotionId;
+          sku.promotionEndTime = item.promotionEndTime;
+        }
+      });
+    });
+
+    // 选择有 promotionPrice 且最小的
+    state.settlementSku = state.goodsInfo.skus
+      .filter((sku) => sku.stock > 0 && sku.promotionPrice > 0)
+      .reduce((prev, curr) => (prev.promotionPrice < curr.promotionPrice ? prev : curr));
+
+    // 设置满减送活动
+    if (data.rewardActivity) {
+      state.rewardActivity = data.rewardActivity;
+    }
+  }
+
   onLoad((options) => {
   onLoad((options) => {
     // 非法参数
     // 非法参数
     if (!options.id) {
     if (!options.id) {
@@ -278,7 +369,6 @@
       // 加载到商品
       // 加载到商品
       state.skeletonLoading = false;
       state.skeletonLoading = false;
       state.goodsInfo = res.data;
       state.goodsInfo = res.data;
-
       // 加载是否收藏
       // 加载是否收藏
       if (isLogin.value) {
       if (isLogin.value) {
         FavoriteApi.isFavoriteExists(state.goodsId, 'goods').then((res) => {
         FavoriteApi.isFavoriteExists(state.goodsId, 'goods').then((res) => {
@@ -293,13 +383,15 @@
     // 2. 加载优惠劵信息
     // 2. 加载优惠劵信息
     getCoupon();
     getCoupon();
 
 
-    // 3. 获得单个商品,进行中的拼团、秒杀、砍价活动信息
+    // 3. 加载营销活动信息
     ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => {
     ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => {
       if (res.code !== 0) {
       if (res.code !== 0) {
         return;
         return;
       }
       }
       state.activityList = res.data;
       state.activityList = res.data;
     });
     });
+    //获取结算信息
+    getSettlementByIds(state.goodsId);
   });
   });
 </script>
 </script>
 
 
@@ -448,4 +540,101 @@
       color: #333333;
       color: #333333;
     }
     }
   }
   }
+
+  // 限时折扣
+  .discount {
+    width: 750rpx;
+    height: 100rpx;
+    // background-color: red;
+    overflow: hidden;
+    position: relative;
+  }
+
+  .disImg {
+    width: 750rpx;
+    height: 100rpx;
+    position: absolute;
+    top: 0;
+    z-index: -1;
+  }
+
+  .discountCont {
+    width: 680rpx;
+    height: 90rpx;
+    margin: 10rpx auto 0 auto;
+    // background-color: gold;
+  }
+
+  .disContT {
+    width: 680rpx;
+    height: 50rpx;
+    display: flex;
+    justify-content: space-between;
+  }
+
+  .disContT1 {
+    width: 400rpx;
+    height: 50rpx;
+    // background-color: green;
+    display: flex;
+    justify-content: flex-start;
+    align-items: center;
+  }
+
+  .disContT2 {
+    width: 200rpx;
+    height: 50rpx;
+    line-height: 50rpx;
+    // background-color: gold;
+    font-size: 30rpx;
+    text-align: end;
+    color: white;
+    font-weight: bolder;
+    font-style: oblique 20deg;
+    letter-spacing: 0.1rem;
+  }
+
+  .disContT1P {
+    color: white;
+    font-weight: bold;
+    font-size: 28rpx;
+  }
+
+  .disContT1End {
+    // width: 180rpx;
+    padding: 0 10rpx;
+    height: 30rpx;
+    line-height: 28rpx;
+    text-align: center;
+    font-weight: bold;
+    background-color: white;
+    color: #ff3000;
+    font-size: 23rpx;
+    border-radius: 20rpx;
+    margin-left: 10rpx;
+  }
+
+  .disContB {
+    width: 680rpx;
+    height: 40rpx;
+    display: flex;
+    justify-content: space-between;
+    font-size: 20rpx;
+    color: white;
+    align-items: center;
+  }
+
+  .disContB1 {
+    width: 300rpx;
+    height: 40rpx;
+    line-height: 40rpx;
+  }
+
+  .disContB2 {
+    width: 300rpx;
+    height: 40rpx;
+    line-height: 40rpx;
+    display: flex;
+    justify-content: flex-end;
+  }
 </style>
 </style>

+ 196 - 0
sheep/components/countDown/index.vue

@@ -0,0 +1,196 @@
+<!-- TODO 霖:是不是怎么复用 s-count-down 组件 -->
+<template>
+  <view class="time" :style="justifyLeft">
+    <text class="" v-if="tipText">{{ tipText }}</text>
+    <text
+      class="styleAll p6"
+      v-if="isDay === true"
+      :style="{ background: bgColor.bgColor, color: bgColor.Color }"
+      >{{ day }}{{ bgColor.isDay ? '天' : '' }}</text
+    >
+    <text
+      class="timeTxt"
+      v-if="dayText"
+      :style="{ width: bgColor.timeTxtwidth, color: bgColor.bgColor }"
+      >{{ dayText }}</text
+    >
+    <text
+      class="styleAll"
+      :class="isCol ? 'timeCol' : ''"
+      :style="{ background: bgColor.bgColor, color: bgColor.Color, width: bgColor.width }"
+      >{{ hour }}</text
+    >
+    <text
+      class="timeTxt"
+      v-if="hourText"
+      :class="isCol ? 'whit' : ''"
+      :style="{ width: bgColor.timeTxtwidth, color: bgColor.bgColor }"
+      >{{ hourText }}</text
+    >
+    <text
+      class="styleAll"
+      :class="isCol ? 'timeCol' : ''"
+      :style="{ background: bgColor.bgColor, color: bgColor.Color, width: bgColor.width }"
+      >{{ minute }}</text
+    >
+    <text
+      class="timeTxt"
+      v-if="minuteText"
+      :class="isCol ? 'whit' : ''"
+      :style="{ width: bgColor.timeTxtwidth, color: bgColor.bgColor }"
+      >{{ minuteText }}</text
+    >
+    <text
+      class="styleAll"
+      :class="isCol ? 'timeCol' : ''"
+      :style="{ background: bgColor.bgColor, color: bgColor.Color, width: bgColor.width }"
+      >{{ second }}</text
+    >
+    <text class="timeTxt" v-if="secondText">{{ secondText }}</text>
+  </view>
+</template>
+
+<script>
+  export default {
+    name: 'countDown',
+    props: {
+      justifyLeft: {
+        type: String,
+        default: '',
+      },
+      //距离开始提示文字
+      tipText: {
+        type: String,
+        default: '倒计时',
+      },
+      dayText: {
+        type: String,
+        default: '天',
+      },
+      hourText: {
+        type: String,
+        default: '时',
+      },
+      minuteText: {
+        type: String,
+        default: '分',
+      },
+      secondText: {
+        type: String,
+        default: '秒',
+      },
+      datatime: {
+        type: Number,
+        default: 0,
+      },
+      isDay: {
+        type: Boolean,
+        default: true,
+      },
+      isCol: {
+        type: Boolean,
+        default: false,
+      },
+      bgColor: {
+        type: Object,
+        default: null,
+      },
+    },
+    data: function () {
+      return {
+        day: '00',
+        hour: '00',
+        minute: '00',
+        second: '00',
+      };
+    },
+    created: function () {
+      this.show_time();
+    },
+    mounted: function () {},
+    methods: {
+      show_time: function () {
+        let that = this;
+
+        function runTime() {
+          //时间函数
+          let intDiff = that.datatime - Date.parse(new Date()) / 1000; //获取数据中的时间戳的时间差;
+          let day = 0,
+            hour = 0,
+            minute = 0,
+            second = 0;
+          if (intDiff > 0) {
+            //转换时间
+            if (that.isDay === true) {
+              day = Math.floor(intDiff / (60 * 60 * 24));
+            } else {
+              day = 0;
+            }
+            hour = Math.floor(intDiff / (60 * 60)) - day * 24;
+            minute = Math.floor(intDiff / 60) - day * 24 * 60 - hour * 60;
+            second = Math.floor(intDiff) - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60;
+            if (hour <= 9) hour = '0' + hour;
+            if (minute <= 9) minute = '0' + minute;
+            if (second <= 9) second = '0' + second;
+            that.day = day;
+            that.hour = hour;
+            that.minute = minute;
+            that.second = second;
+          } else {
+            that.day = '00';
+            that.hour = '00';
+            that.minute = '00';
+            that.second = '00';
+          }
+        }
+        runTime();
+        setInterval(runTime, 1000);
+      },
+    },
+  };
+</script>
+
+<style scoped>
+  .p6 {
+    padding: 0 8rpx;
+  }
+  .styleAll {
+    /* color: #fff; */
+    font-size: 24rpx;
+    height: 36rpx;
+    line-height: 36rpx;
+    border-radius: 6rpx;
+    text-align: center;
+    /* padding: 0 6rpx; */
+  }
+  .timeTxt {
+    text-align: center;
+    /* width: 16rpx; */
+    height: 36rpx;
+    line-height: 36rpx;
+    display: inline-block;
+  }
+  .whit {
+    color: #fff !important;
+  }
+  .time {
+    display: flex;
+    justify-content: center;
+  }
+
+  .red {
+    color: #fc4141;
+    margin: 0 4rpx;
+  }
+
+  .timeCol {
+    /* width: 40rpx;
+    height: 40rpx;
+    line-height: 40rpx;
+    text-align:center;
+    border-radius: 6px;
+    background: #fff;
+    font-size: 24rpx; */
+    color: #e93323;
+  }
+</style>

+ 44 - 101
sheep/components/s-activity-pop/s-activity-pop.vue

@@ -3,66 +3,32 @@
   <su-popup :show="show" type="bottom" round="20" @close="emits('close')" showClose>
   <su-popup :show="show" type="bottom" round="20" @close="emits('close')" showClose>
     <view class="model-box">
     <view class="model-box">
       <view class="title ss-m-t-16 ss-m-l-20 ss-flex">优惠</view>
       <view class="title ss-m-t-16 ss-m-l-20 ss-flex">优惠</view>
-      <view v-if="state.activityMap[state.activityInfo[0]?.id]?.reduc">
+      <view v-if="state.rewardActivity && state.rewardActivity.id > 0">
         <view class="titleLi">促销</view>
         <view class="titleLi">促销</view>
-        <scroll-view class="model-content" scroll-y :scroll-with-animation="false" :enable-back-to-top="true">
-          <view class="actBox">
-            <view class="boxCont ss-flex ss-col-top ss-m-b-40" @tap="onGoodsList(state.activityInfo[0])">
+        <scroll-view
+          class="model-content"
+          scroll-y
+          :scroll-with-animation="false"
+          :enable-back-to-top="true"
+        >
+          <view
+            class="actBox"
+            v-for="(item, index) in state.rewardActivity.ruleDescriptions"
+            :key="index"
+          >
+            <view
+              class="boxCont ss-flex ss-col-top ss-m-b-40"
+              @tap="onGoodsList(state.rewardActivity)"
+            >
               <view class="model-content-tag ss-flex ss-row-center">满减</view>
               <view class="model-content-tag ss-flex ss-row-center">满减</view>
               <view class="model-content-title">
               <view class="model-content-title">
                 <view class="contBu">
                 <view class="contBu">
-                  <text v-for="(item,index) in state.activityMap[state.activityInfo[0]?.id]?.reduc"
-                        :key="index">满{{fen2yuan(item.discountPrice)}}元减{{fen2yuan(item.limit)}}元;</text>
+                  <text>{{ item }}</text>
                 </view>
                 </view>
                 <view class="ss-m-b-24 cotBu-txt">
                 <view class="ss-m-b-24 cotBu-txt">
-                  {{formatDateRange(state.activityInfo[0]?.startTime,state.activityInfo[0]?.endTime)}}
-                </view>
-              </view>
-              <text class="cicon-forward" />
-            </view>
-          </view>
-          <view class="actBox">
-            <view class="boxCont ss-flex ss-col-top ss-m-b-40" @tap="onGoodsList(state.activityInfo[0])">
-              <view class="model-content-tag ss-flex ss-row-center">包邮</view>
-              <view class="model-content-title">
-                <view class="contBu">
-                  <text v-for="(item,index) in state.activityMap[state.activityInfo[0]?.id]?.ship"
-                        :key="index" v-show="item.bull">满{{fen2yuan(item.discountPrice)}}元包邮;</text>
-                </view>
-                <view class="ss-m-b-24 cotBu-txt">
-                  {{formatDateRange(state.activityInfo[0]?.startTime,state.activityInfo[0]?.endTime)}}
-                </view>
-              </view>
-              <text class="cicon-forward" />
-            </view>
-          </view>
-          <view class="actBox">
-            <view class="boxCont ss-flex ss-col-top ss-m-b-40" @tap="onGoodsList(state.activityInfo[0])">
-              <view class="model-content-tag ss-flex ss-row-center">送积分</view>
-              <view class="model-content-title">
-                <view class="contBu">
-                  <text v-for="(item,index) in state.activityMap[state.activityInfo[0]?.id]?.scor"
-                        :key="index"
-                        v-show="item.bull">满{{fen2yuan(item.discountPrice)}}元送{{item.value}}积分;</text>
-                </view>
-                <view class="ss-m-b-24 cotBu-txt">
-                  {{formatDateRange(state.activityInfo[0]?.startTime,state.activityInfo[0]?.endTime)}}
-                </view>
-              </view>
-              <text class="cicon-forward" />
-            </view>
-          </view>
-          <view class="actBox">
-            <view class="boxCont ss-flex ss-col-top ss-m-b-40" @tap="onGoodsList(state.activityInfo[0])">
-              <view class="model-content-tag ss-flex ss-row-center">送优惠券</view>
-              <view class="model-content-title">
-                <view class="contBu">
-                  <text v-for="(item,index) in state.activityMap[state.activityInfo[0]?.id]?.cou"
-                        :key="index"
-                        v-show="item.bull">满{{fen2yuan(item.discountPrice)}}元送{{item.value}}张优惠券;</text>
-                </view>
-                <view class="ss-m-b-24 cotBu-txt">
-                  {{formatDateRange(state.activityInfo[0]?.startTime,state.activityInfo[0]?.endTime)}}
+                  {{ sheep.$helper.timeFormat(state.rewardActivity.startTime, 'yyyy.mm.dd') }}
+                  -
+                  {{ sheep.$helper.timeFormat(state.rewardActivity.endTime, 'yyyy.mm.dd') }}
                 </view>
                 </view>
               </view>
               </view>
               <text class="cicon-forward" />
               <text class="cicon-forward" />
@@ -71,31 +37,33 @@
         </scroll-view>
         </scroll-view>
       </view>
       </view>
       <view class="titleLi">可领优惠券</view>
       <view class="titleLi">可领优惠券</view>
-      <scroll-view class="model-content" scroll-y :scroll-with-animation="false" :enable-back-to-top="true">
+      <scroll-view
+        class="model-content"
+        scroll-y
+        :scroll-with-animation="false"
+        :enable-back-to-top="true"
+      >
         <view class="actBox" v-for="item in state.couponInfo" :key="item.id">
         <view class="actBox" v-for="item in state.couponInfo" :key="item.id">
           <view class="boxCont ss-flex ss-col-top ss-m-b-40">
           <view class="boxCont ss-flex ss-col-top ss-m-b-40">
             <view class="model-content-tag2">
             <view class="model-content-tag2">
-              <view class="usePrice">
-                ¥{{fen2yuan(item.discountPrice)}}
-              </view>
-              <view class="impose">
-                满¥{{fen2yuan(item.usePrice)}}可用
-              </view>
+              <view class="usePrice"> ¥{{ fen2yuan(item.discountPrice) }} </view>
+              <view class="impose"> 满¥{{ fen2yuan(item.usePrice) }}可用 </view>
             </view>
             </view>
             <view class="model-content-title2">
             <view class="model-content-title2">
               <view class="contBu">
               <view class="contBu">
-                {{item.name}}
+                {{ item.name }}
               </view>
               </view>
               <view class="ss-m-b-24 cotBu-txt">
               <view class="ss-m-b-24 cotBu-txt">
-                {{item.validityType==1?formatDateRange(item.validStartTime,item.validEndTime) : '领取后'+item.fixedStartTerm+'-'+item.fixedEndTerm +'天可用'}}
+                {{
+                  item.validityType == 1
+                    ? sheep.$helper.timeFormat(item.validStartTime, 'yyyy.mm.dd') -
+                      sheep.$helper.timeFormat(item.validEndTime, 'yyyy.mm.dd')
+                    : '领取后' + item.fixedStartTerm + '-' + item.fixedEndTerm + '天可用'
+                }}
               </view>
               </view>
             </view>
             </view>
-            <view class="coupon" @click.stop="getBuy(item.id)" v-if="item.canTake">
-              立即领取
-            </view>
-            <view class="coupon2" v-else>
-              已领取
-            </view>
+            <view class="coupon" @click.stop="getBuy(item.id)" v-if="item.canTake"> 立即领取 </view>
+            <view class="coupon2" v-else> 已领取 </view>
           </view>
           </view>
         </view>
         </view>
       </scroll-view>
       </scroll-view>
@@ -104,21 +72,12 @@
 </template>
 </template>
 <script setup>
 <script setup>
   import sheep from '@/sheep';
   import sheep from '@/sheep';
-  import {
-    computed,
-    reactive,
-    watch
-  } from 'vue';
-  import RewardActivityApi from '@/sheep/api/promotion/rewardActivity';
-  import {
-    fen2yuan,
-    formatDateRange,
-    handActitList
-  } from '@/sheep/hooks/useGoods';
+  import { computed, reactive } from 'vue';
+  import { fen2yuan } from '@/sheep/hooks/useGoods';
   const props = defineProps({
   const props = defineProps({
     modelValue: {
     modelValue: {
       type: Object,
       type: Object,
-      default () {},
+      default() {},
     },
     },
     show: {
     show: {
       type: Boolean,
       type: Boolean,
@@ -127,26 +86,10 @@
   });
   });
   const emits = defineEmits(['close']);
   const emits = defineEmits(['close']);
   const state = reactive({
   const state = reactive({
-    activityInfo: computed(() => props.modelValue.activityInfo),
-    activityMap: {},
-    couponInfo: computed(() => props.modelValue.couponInfo)
+    rewardActivity: computed(() => props.modelValue.rewardActivity),
+    couponInfo: computed(() => props.modelValue.couponInfo),
   });
   });
-  watch(
-    () => props.show,
-    () => {
-      // 展示的情况下,加载每个活动的详细信息
-      if (props.show) {
-        state.activityInfo?.forEach(activity => {
-          RewardActivityApi.getRewardActivity(activity.id).then(res => {
-            if (res.code !== 0) {
-              return;
-            }
-            state.activityMap[activity.id] = handActitList(res.data.rules);
-          })
-        });
-      }
-    },
-  );
+
   // 领取优惠劵
   // 领取优惠劵
   const getBuy = (id) => {
   const getBuy = (id) => {
     emits('get', id);
     emits('get', id);
@@ -298,4 +241,4 @@
     text-align: center;
     text-align: center;
     font-size: 25rpx;
     font-size: 25rpx;
   }
   }
-</style>
+</style>

+ 0 - 1
sheep/components/s-goods-column/s-goods-column.vue

@@ -482,7 +482,6 @@
   const iconShow = handle();
   const iconShow = handle();
 
 
   function handle() {
   function handle() {
-    debugger;
     if (props.data.discountPrice === null && props.data.vipPrice === null) {
     if (props.data.discountPrice === null && props.data.vipPrice === null) {
       // 如果两个值都为 null,则不展示任何内容
       // 如果两个值都为 null,则不展示任何内容
       return '';
       return '';

+ 53 - 29
sheep/components/s-select-sku/s-select-sku.vue

@@ -5,18 +5,33 @@
     <view class="ss-modal-box bg-white ss-flex-col">
     <view class="ss-modal-box bg-white ss-flex-col">
       <view class="modal-header ss-flex ss-col-center">
       <view class="modal-header ss-flex ss-col-center">
         <view class="header-left ss-m-r-30">
         <view class="header-left ss-m-r-30">
-          <image class="sku-image" :src="state.selectedSku.picUrl || goodsInfo.picUrl" mode="aspectFill" />
+          <image
+            class="sku-image"
+            :src="state.selectedSku.picUrl || goodsInfo.picUrl"
+            mode="aspectFill"
+          />
         </view>
         </view>
         <view class="header-right ss-flex-col ss-row-between ss-flex-1">
         <view class="header-right ss-flex-col ss-row-between ss-flex-1">
           <view class="goods-title ss-line-2">{{ goodsInfo.name }}</view>
           <view class="goods-title ss-line-2">{{ goodsInfo.name }}</view>
           <view class="header-right-bottom ss-flex ss-col-center ss-row-between">
           <view class="header-right-bottom ss-flex ss-col-center ss-row-between">
             <view class="ss-flex">
             <view class="ss-flex">
               <view class="price-text">
               <view class="price-text">
-                {{ fen2yuan( state.selectedSku.price || goodsInfo.price) }}
-                <text v-if="state.selectedSku.type == 6"><text class="iconBox">会员价</text><text
-                  class="origin-price-text">{{fen2yuan(state.selectedSku.oldPrice)}}</text></text>
-                <text v-if="state.selectedSku.type == 4"><text class="iconBox">限时优惠</text><text
-                  class="origin-price-text">{{fen2yuan(state.selectedSku.oldPrice)}}</text></text>
+                {{
+                  fen2yuan(
+                    state.selectedSku.promotionPrice || state.selectedSku.price || goodsInfo.price,
+                  )
+                }}
+                <text v-if="state.selectedSku.promotionType > 0">
+                  <text class="iconBox" v-if="state.selectedSku.promotionType === 4">
+                    限时优惠
+                  </text>
+                  <text class="iconBox" v-else-if="state.selectedSku.promotionType === 6">
+                    会员价
+                  </text>
+                  <text class="origin-price-text">
+                    {{ fen2yuan(state.selectedSku.price) }}
+                  </text>
+                </text>
               </view>
               </view>
             </view>
             </view>
             <view class="stock-text ss-m-l-20">
             <view class="stock-text ss-m-l-20">
@@ -32,22 +47,34 @@
           <view class="sku-item ss-m-b-20" v-for="property in propertyList" :key="property.id">
           <view class="sku-item ss-m-b-20" v-for="property in propertyList" :key="property.id">
             <view class="label-text ss-m-b-20">{{ property.name }}</view>
             <view class="label-text ss-m-b-20">{{ property.name }}</view>
             <view class="ss-flex ss-col-center ss-flex-wrap">
             <view class="ss-flex ss-col-center ss-flex-wrap">
-              <button class="ss-reset-button spec-btn" v-for="value in property.values" :class="[
+              <button
+                class="ss-reset-button spec-btn"
+                v-for="value in property.values"
+                :class="[
                   {
                   {
                     'ui-BG-Main-Gradient': state.currentPropertyArray[property.id] === value.id,
                     'ui-BG-Main-Gradient': state.currentPropertyArray[property.id] === value.id,
                   },
                   },
                   {
                   {
                     'disabled-btn': value.disabled === true,
                     'disabled-btn': value.disabled === true,
                   },
                   },
-                ]" :key="value.id" :disabled="value.disabled === true" @tap="onSelectSku(property.id, value.id)">
+                ]"
+                :key="value.id"
+                :disabled="value.disabled === true"
+                @tap="onSelectSku(property.id, value.id)"
+              >
                 {{ value.name }}
                 {{ value.name }}
               </button>
               </button>
             </view>
             </view>
           </view>
           </view>
           <view class="buy-num-box ss-flex ss-col-center ss-row-between ss-m-b-40">
           <view class="buy-num-box ss-flex ss-col-center ss-row-between ss-m-b-40">
             <view class="label-text">购买数量</view>
             <view class="label-text">购买数量</view>
-            <su-number-box :min="1" :max="state.selectedSku.stock" :step="1"
-                           v-model="state.selectedSku.goods_num" @change="onNumberChange($event)" />
+            <su-number-box
+              :min="1"
+              :max="state.selectedSku.stock"
+              :step="1"
+              v-model="state.selectedSku.goods_num"
+              @change="onNumberChange($event)"
+            />
           </view>
           </view>
         </scroll-view>
         </scroll-view>
       </view>
       </view>
@@ -55,7 +82,9 @@
       <!-- 操作区 -->
       <!-- 操作区 -->
       <view class="modal-footer border-top">
       <view class="modal-footer border-top">
         <view class="buy-box ss-flex ss-col-center ss-flex ss-col-center ss-row-center">
         <view class="buy-box ss-flex ss-col-center ss-flex ss-col-center ss-row-center">
-          <button class="ss-reset-button add-btn ui-Shadow-Main" @tap="onAddCart">加入购物车</button>
+          <button class="ss-reset-button add-btn ui-Shadow-Main" @tap="onAddCart"
+            >加入购物车</button
+          >
           <button class="ss-reset-button buy-btn ui-Shadow-Main" @tap="onBuy">立即购买</button>
           <button class="ss-reset-button buy-btn ui-Shadow-Main" @tap="onBuy">立即购买</button>
         </view>
         </view>
       </view>
       </view>
@@ -64,28 +93,20 @@
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-  import {
-    computed,
-    reactive,
-    watch
-  } from 'vue';
+  import { computed, reactive, watch } from 'vue';
   import sheep from '@/sheep';
   import sheep from '@/sheep';
-  import {
-    formatStock,
-    convertProductPropertyList,
-    fen2yuan
-  } from '@/sheep/hooks/useGoods';
+  import { formatStock, convertProductPropertyList, fen2yuan } from '@/sheep/hooks/useGoods';
 
 
   const emits = defineEmits(['change', 'addCart', 'buy', 'close']);
   const emits = defineEmits(['change', 'addCart', 'buy', 'close']);
   const props = defineProps({
   const props = defineProps({
     goodsInfo: {
     goodsInfo: {
       type: Object,
       type: Object,
-      default () {},
+      default() {},
     },
     },
     show: {
     show: {
       type: Boolean,
       type: Boolean,
       default: false,
       default: false,
-    }
+    },
   });
   });
 
 
   const state = reactive({
   const state = reactive({
@@ -98,7 +119,7 @@
   const skuList = computed(() => {
   const skuList = computed(() => {
     let skuPrices = props.goodsInfo.skus;
     let skuPrices = props.goodsInfo.skus;
     for (let price of skuPrices) {
     for (let price of skuPrices) {
-      price.value_id_array = price.properties.map((item) => item.valueId)
+      price.value_id_array = price.properties.map((item) => item.valueId);
     }
     }
     return skuPrices;
     return skuPrices;
   });
   });
@@ -107,7 +128,8 @@
     () => state.selectedSku,
     () => state.selectedSku,
     (newVal) => {
     (newVal) => {
       emits('change', newVal);
       emits('change', newVal);
-    }, {
+    },
+    {
       immediate: true, // 立即执行
       immediate: true, // 立即执行
       deep: true, // 深度监听
       deep: true, // 深度监听
     },
     },
@@ -216,8 +238,7 @@
       // 如果当前 property id 不存在于有库存的 SKU 中,则禁用
       // 如果当前 property id 不存在于有库存的 SKU 中,则禁用
       for (let valueIndex in propertyList[propertyIndex]['values']) {
       for (let valueIndex in propertyList[propertyIndex]['values']) {
         propertyList[propertyIndex]['values'][valueIndex]['disabled'] =
         propertyList[propertyIndex]['values'][valueIndex]['disabled'] =
-          noChooseValueIds.indexOf(propertyList[propertyIndex]['values'][valueIndex]['id']) <
-          0; // true 禁用 or false 不禁用
+          noChooseValueIds.indexOf(propertyList[propertyIndex]['values'][valueIndex]['id']) < 0; // true 禁用 or false 不禁用
       }
       }
     }
     }
   }
   }
@@ -247,7 +268,10 @@
   function onSelectSku(propertyId, valueId) {
   function onSelectSku(propertyId, valueId) {
     // 清空已选择
     // 清空已选择
     let isChecked = true; // 选中 or 取消选中
     let isChecked = true; // 选中 or 取消选中
-    if (state.currentPropertyArray[propertyId] !== undefined && state.currentPropertyArray[propertyId] === valueId) {
+    if (
+      state.currentPropertyArray[propertyId] !== undefined &&
+      state.currentPropertyArray[propertyId] === valueId
+    ) {
       // 点击已被选中的,删除并填充 ''
       // 点击已被选中的,删除并填充 ''
       isChecked = false;
       isChecked = false;
       state.currentPropertyArray.splice(propertyId, 1, '');
       state.currentPropertyArray.splice(propertyId, 1, '');
@@ -437,4 +461,4 @@
       content: '¥';
       content: '¥';
     }
     }
   }
   }
-</style>
+</style>

+ 48 - 149
sheep/hooks/useGoods.js

@@ -1,11 +1,7 @@
-import {
-  ref
-} from 'vue';
+import { ref } from 'vue';
 import dayjs from 'dayjs';
 import dayjs from 'dayjs';
 import $url from '@/sheep/url';
 import $url from '@/sheep/url';
-import {
-  formatDate
-} from '@/sheep/util';
+import { formatDate } from '@/sheep/util';
 
 
 /**
 /**
  * 格式化销量
  * 格式化销量
@@ -15,7 +11,7 @@ import {
  */
  */
 export function formatSales(type, num) {
 export function formatSales(type, num) {
   let prefix = type !== 'exact' && num < 10 ? '销量' : '已售';
   let prefix = type !== 'exact' && num < 10 ? '销量' : '已售';
-  return formatNum(prefix, type, num)
+  return formatNum(prefix, type, num);
 }
 }
 
 
 /**
 /**
@@ -25,10 +21,9 @@ export function formatSales(type, num) {
  * @return {string} 格式化后的销量字符串
  * @return {string} 格式化后的销量字符串
  */
  */
 export function formatExchange(type, num) {
 export function formatExchange(type, num) {
-  return formatNum('已兑换', type, num)
+  return formatNum('已兑换', type, num);
 }
 }
 
 
-
 /**
 /**
  * 格式化库存
  * 格式化库存
  * @param {'exact' | any} type 格式类型:exact=精确值,其它=大致数量
  * @param {'exact' | any} type 格式类型:exact=精确值,其它=大致数量
@@ -36,7 +31,7 @@ export function formatExchange(type, num) {
  * @return {string} 格式化后的销量字符串
  * @return {string} 格式化后的销量字符串
  */
  */
 export function formatStock(type, num) {
 export function formatStock(type, num) {
-  return formatNum('库存', type, num)
+  return formatNum('库存', type, num);
 }
 }
 
 
 /**
 /**
@@ -47,7 +42,7 @@ export function formatStock(type, num) {
  * @return {string} 格式化后的销量字符串
  * @return {string} 格式化后的销量字符串
  */
  */
 export function formatNum(prefix, type, num) {
 export function formatNum(prefix, type, num) {
-  num = (num || 0);
+  num = num || 0;
   // 情况一:精确数值
   // 情况一:精确数值
   if (type === 'exact') {
   if (type === 'exact') {
     return prefix + num;
     return prefix + num;
@@ -71,7 +66,7 @@ export function formatPrice(e) {
 }
 }
 
 
 // 视频格式后缀列表
 // 视频格式后缀列表
-const VIDEO_SUFFIX_LIST = ['.avi', '.mp4']
+const VIDEO_SUFFIX_LIST = ['.avi', '.mp4'];
 
 
 /**
 /**
  * 转换商品轮播的链接列表:根据链接的后缀,判断是视频链接还是图片链接
  * 转换商品轮播的链接列表:根据链接的后缀,判断是视频链接还是图片链接
@@ -80,15 +75,19 @@ const VIDEO_SUFFIX_LIST = ['.avi', '.mp4']
  * @return {{src: string, type: 'video' | 'image' }[]}  转换后的链接列表
  * @return {{src: string, type: 'video' | 'image' }[]}  转换后的链接列表
  */
  */
 export function formatGoodsSwiper(urlList) {
 export function formatGoodsSwiper(urlList) {
-  return urlList?.filter(url => url).map((url, key) => {
-    const isVideo = VIDEO_SUFFIX_LIST.some(suffix => url.includes(suffix));
-    const type = isVideo ? 'video' : 'image'
-    const src = $url.cdn(url);
-    return {
-      type,
-      src
-    }
-  }) || [];
+  return (
+    urlList
+      ?.filter((url) => url)
+      .map((url, key) => {
+        const isVideo = VIDEO_SUFFIX_LIST.some((suffix) => url.includes(suffix));
+        const type = isVideo ? 'video' : 'image';
+        const src = $url.cdn(url);
+        return {
+          type,
+          src,
+        };
+      }) || []
+  );
 }
 }
 
 
 /**
 /**
@@ -101,9 +100,7 @@ export function formatOrderColor(order) {
   if (order.status === 0) {
   if (order.status === 0) {
     return 'info-color';
     return 'info-color';
   }
   }
-  if (order.status === 10 ||
-    order.status === 20 ||
-    (order.status === 30 && !order.commentStatus)) {
+  if (order.status === 10 || order.status === 20 || (order.status === 30 && !order.commentStatus)) {
     return 'warning-color';
     return 'warning-color';
   }
   }
   if (order.status === 30 && order.commentStatus) {
   if (order.status === 30 && order.commentStatus) {
@@ -146,7 +143,7 @@ export function formatOrderStatus(order) {
  */
  */
 export function formatOrderStatusDescription(order) {
 export function formatOrderStatusDescription(order) {
   if (order.status === 0) {
   if (order.status === 0) {
-    return `请在 ${ formatDate(order.payExpireTime) } 前完成支付`;
+    return `请在 ${formatDate(order.payExpireTime)} 前完成支付`;
   }
   }
   if (order.status === 10) {
   if (order.status === 10) {
     return '商家未发货,请耐心等待';
     return '商家未发货,请耐心等待';
@@ -169,24 +166,30 @@ export function formatOrderStatusDescription(order) {
  * @param order 订单
  * @param order 订单
  */
  */
 export function handleOrderButtons(order) {
 export function handleOrderButtons(order) {
-  order.buttons = []
-  if (order.type === 3) { // 查看拼团
+  order.buttons = [];
+  if (order.type === 3) {
+    // 查看拼团
     order.buttons.push('combination');
     order.buttons.push('combination');
   }
   }
-  if (order.status === 20) { // 确认收货
+  if (order.status === 20) {
+    // 确认收货
     order.buttons.push('confirm');
     order.buttons.push('confirm');
   }
   }
-  if (order.logisticsId > 0) { // 查看物流
+  if (order.logisticsId > 0) {
+    // 查看物流
     order.buttons.push('express');
     order.buttons.push('express');
   }
   }
-  if (order.status === 0) { // 取消订单 / 发起支付
+  if (order.status === 0) {
+    // 取消订单 / 发起支付
     order.buttons.push('cancel');
     order.buttons.push('cancel');
     order.buttons.push('pay');
     order.buttons.push('pay');
   }
   }
-  if (order.status === 30 && !order.commentStatus) { // 发起评价
+  if (order.status === 30 && !order.commentStatus) {
+    // 发起评价
     order.buttons.push('comment');
     order.buttons.push('comment');
   }
   }
-  if (order.status === 40) { // 删除订单
+  if (order.status === 40) {
+    // 删除订单
     order.buttons.push('delete');
     order.buttons.push('delete');
   }
   }
 }
 }
@@ -264,10 +267,12 @@ export function formatAfterSaleStatusDescription(afterSale) {
  */
  */
 export function handleAfterSaleButtons(afterSale) {
 export function handleAfterSaleButtons(afterSale) {
   afterSale.buttons = [];
   afterSale.buttons = [];
-  if ([10, 20, 30].includes(afterSale.status)) { // 取消订单
+  if ([10, 20, 30].includes(afterSale.status)) {
+    // 取消订单
     afterSale.buttons.push('cancel');
     afterSale.buttons.push('cancel');
   }
   }
-  if (afterSale.status === 20) { // 退货信息
+  if (afterSale.status === 20) {
+    // 退货信息
     afterSale.buttons.push('delivery');
     afterSale.buttons.push('delivery');
   }
   }
 }
 }
@@ -331,7 +336,7 @@ function getDayjsTime(time) {
  * @returns {string} 元,例如说 1.00 元
  * @returns {string} 元,例如说 1.00 元
  */
  */
 export function fen2yuan(price) {
 export function fen2yuan(price) {
-  return (price / 100.0).toFixed(2)
+  return (price / 100.0).toFixed(2);
 }
 }
 
 
 /**
 /**
@@ -352,134 +357,28 @@ export function convertProductPropertyList(skus) {
   let result = [];
   let result = [];
   for (const sku of skus) {
   for (const sku of skus) {
     if (!sku.properties) {
     if (!sku.properties) {
-      continue
+      continue;
     }
     }
     for (const property of sku.properties) {
     for (const property of sku.properties) {
       // ① 先处理属性
       // ① 先处理属性
-      let resultProperty = result.find(item => item.id === property.propertyId)
+      let resultProperty = result.find((item) => item.id === property.propertyId);
       if (!resultProperty) {
       if (!resultProperty) {
         resultProperty = {
         resultProperty = {
           id: property.propertyId,
           id: property.propertyId,
           name: property.propertyName,
           name: property.propertyName,
-          values: []
-        }
-        result.push(resultProperty)
+          values: [],
+        };
+        result.push(resultProperty);
       }
       }
       // ② 再处理属性值
       // ② 再处理属性值
-      let resultValue = resultProperty.values.find(item => item.id === property.valueId)
+      let resultValue = resultProperty.values.find((item) => item.id === property.valueId);
       if (!resultValue) {
       if (!resultValue) {
         resultProperty.values.push({
         resultProperty.values.push({
           id: property.valueId,
           id: property.valueId,
-          name: property.valueName
-        })
+          name: property.valueName,
+        });
       }
       }
     }
     }
   }
   }
   return result;
   return result;
 }
 }
-
-/**
- * 格式化满减送活动的规则
- *
- * @param activity 活动信息
- * @param rule 优惠规格
- * @returns {string} 规格字符串
- */
-export function formatRewardActivityRule(activity, rule) {
-  if (activity.conditionType === 10) {
-    return `满 ${fen2yuan(rule.limit)} 元减 ${fen2yuan(rule.discountPrice)} 元`;
-  }
-  if (activity.conditionType === 20) {
-    return `满 ${rule.limit} 件减 ${fen2yuan(rule.discountPrice)} 元`;
-  }
-  return '';
-}
-// 新增将时间搓转换为开始时间-结束时间的格式
-export function formatDateRange(startTimestamp, endTimestamp) {
-  // 定义一个辅助函数来格式化时间戳为 YYYY.MM.DD 格式
-  const formatDate = (timestamp) => {
-    const date = new Date(timestamp);
-    const year = date.getFullYear();
-    const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,所以需要+1
-    const day = String(date.getDate()).padStart(2, '0');
-    return `${year}.${month}.${day}`;
-  };
-
-  // 格式化开始和结束时间
-  const start = formatDate(startTimestamp);
-  const end = formatDate(endTimestamp);
-
-  // 返回格式化的日期范围
-  return `${start}-${end}`;
-}
-
-//处理活动信息
-export function handList(orders) {
-  const typeMap = {
-    '1': '秒杀活动',
-    '2': '砍价活动',
-    '3': '拼团活动',
-    '4': '限时折扣',
-    '5': '满减送',
-    '6': '会员折扣',
-    '7': '优惠券',
-    '8': '积分'
-  };
-
-  // 给每个订单对象添加 typeName 属性
-  let updatedOrders = orders.map(order => {
-    return {
-      ...order, // 展开现有的订单对象属性
-      typeName: typeMap[order.type] // 添加 typeName 属性
-    };
-  });
-  return updatedOrders
-};
-//根据skuid来修改价格并添加时间
-export function handListPrice(array,array2) {
-  // 将 array2 转换为一个以 skuId 为键的对象,以便于快速查找
-  const array2Map = array2.reduce((acc, item) => {
-    acc[item.skuId] = { price: item.price, type: item.type,endTime:item.endTime };
-    return acc;
-  }, {});
-
-  // 遍历 array 数组并更新 price 和 type
-  array.forEach(item => {
-    if (array2Map[item.id]) {
-      item.oldPrice = item.price
-      // 如果在 array2Map 中找到了对应的 skuId(即 id)
-      item.price = array2Map[item.id].price;
-      item.type = array2Map[item.id].type;
-      item.endTime = array2Map[item.id].endTime;
-    }
-  });
-
-  // 返回更新后的 array
-  return array;
-};
-
-//处理活动数据
-export function handActitList(rules) {
-  const rules2 = {
-    reduc: rules.map(item => ({
-      discountPrice: item.discountPrice,
-      limit: item.limit,
-      bull: true // 默认为 true
-    })),
-    cou: rules.map(item => ({
-      discountPrice: item.discountPrice,
-      value: item.couponCounts.reduce((acc, count) => acc + count, 0), // 计算 couponCounts 中各项之和
-      bull: item.givePoint // 对应 givePoint
-    })),
-    ship: rules.map(item => ({
-      discountPrice: item.discountPrice,
-      bull: item.freeDelivery // 对应 freeDelivery
-    })),
-    scor: rules.map(item => ({
-      discountPrice: item.discountPrice,
-      value: item.point, // 直接使用 point
-      bull: item.givePoint // 对应 givePoint
-    }))
-  };
-  return rules2
-};

BIN
static/images/dis.png