瀏覽代碼

【功能优化】商城:调整满减送的数据返回

YunaiV 11 月之前
父節點
當前提交
3dad154ca0

+ 1 - 1
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">
-            {{ item.description[1] }}
+            {{ 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" />

+ 659 - 609
pages/goods/index.vue

@@ -1,619 +1,669 @@
 <template>
 <template>
-	<view>
-		<s-layout :onShareAppMessage="shareInfo" navbar="goods">
-			<!-- 标题栏 -->
-			<detailNavbar />
-
-			<!-- 骨架屏 -->
-			<detailSkeleton v-if="state.skeletonLoading" />
-			<!-- 下架/售罄提醒 -->
-			<s-empty v-else-if="state.goodsInfo === null" text="商品不存在或已下架" icon="/static/soldout-empty.png" showAction
-				actionText="再逛逛" actionUrl="/pages/goods/list" />
-			<block v-else>
-				<view class="detail-swiper-selector">
-					<!-- 商品轮播图  -->
-					<su-swiper class="ss-m-b-14" isPreview :list="formatGoodsSwiper(state.goodsInfo.sliderPicUrls)"
-						otStyle="tag" imageMode="widthFix" dotCur="bg-mask-40" :seizeHeight="750" />
-					<!-- 限时折扣/会员价的优惠信息 -->
-					<view class="discount" v-if="state.settlementSku && state.settlementSku.id && state.settlementSku.promotionPrice">
-						<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-30 ss-p-x-20">
-						<!-- 没有限时折扣/会员价的优惠信息时,展示的价格信息 -->
-						<view class="ss-flex ss-row-between ss-col-center ss-m-b-26"
-							v-if="!(state.settlementSku.promotionPrice)">
-							<view class="price-box ss-flex ss-col-bottom">
-								<view class="price-text ss-m-r-16">
-									{{ fen2yuan(state.selectedSku.price || state.goodsInfo.price) }}
-								</view>
-								<view class="origin-price-text" v-if="state.goodsInfo.marketPrice > 0">
-									{{ fen2yuan(state.selectedSku.marketPrice || state.goodsInfo.marketPrice) }}
-								</view>
-							</view>
-							<view class="sales-text">
-								{{ formatSales('exact', state.goodsInfo.salesCount) }}
-							</view>
-						</view>
-						<view class="discounts-box ss-flex ss-row-between ss-m-b-28">
-							<!-- 查看满减送的描述 -->
-							<div class="tag-content">
-								<view class="tag-box ss-flex">
-									<!-- <view
+  <view>
+    <s-layout :onShareAppMessage="shareInfo" navbar="goods">
+      <!-- 标题栏 -->
+      <detailNavbar />
+
+      <!-- 骨架屏 -->
+      <detailSkeleton v-if="state.skeletonLoading" />
+      <!-- 下架/售罄提醒 -->
+      <s-empty
+        v-else-if="state.goodsInfo === null"
+        text="商品不存在或已下架"
+        icon="/static/soldout-empty.png"
+        showAction
+        actionText="再逛逛"
+        actionUrl="/pages/goods/list"
+      />
+      <block v-else>
+        <view class="detail-swiper-selector">
+          <!-- 商品轮播图  -->
+          <su-swiper
+            class="ss-m-b-14"
+            isPreview
+            :list="formatGoodsSwiper(state.goodsInfo.sliderPicUrls)"
+            otStyle="tag"
+            imageMode="widthFix"
+            dotCur="bg-mask-40"
+            :seizeHeight="750"
+          />
+          <!-- 限时折扣/会员价的优惠信息 -->
+          <view
+            class="discount"
+            v-if="
+              state.settlementSku && state.settlementSku.id && state.settlementSku.promotionPrice
+            "
+          >
+            <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-30 ss-p-x-20">
+            <!-- 没有限时折扣/会员价的优惠信息时,展示的价格信息 -->
+            <view
+              class="ss-flex ss-row-between ss-col-center ss-m-b-26"
+              v-if="!state.settlementSku.promotionPrice"
+            >
+              <view class="price-box ss-flex ss-col-bottom">
+                <view class="price-text ss-m-r-16">
+                  {{ fen2yuan(state.selectedSku.price || state.goodsInfo.price) }}
+                </view>
+                <view class="origin-price-text" v-if="state.goodsInfo.marketPrice > 0">
+                  {{ fen2yuan(state.selectedSku.marketPrice || state.goodsInfo.marketPrice) }}
+                </view>
+              </view>
+              <view class="sales-text">
+                {{ formatSales('exact', state.goodsInfo.salesCount) }}
+              </view>
+            </view>
+            <view class="discounts-box ss-flex ss-row-between ss-m-b-28">
+              <!-- 查看优惠劵的描述 -->
+              <view
+                class="tag ss-m-r-10"
+                v-for="coupon in state.couponInfo.slice(0, 1)"
+                :key="coupon.id"
+                @tap="onOpenActivity"
+              >
+                [劵]满{{ fen2yuanSimple(coupon.usePrice) }}元{{
+                  coupon.discountType === 1
+                    ? '减' + fen2yuanSimple(coupon.discountPrice) + '元'
+                    : '打' + formatDiscountPercent(coupon.discountPercent) + '折'
+                }}
+              </view>
+              <!-- 查看满减送的描述 -->
+              <div class="tag-content">
+                <view class="tag-box ss-flex">
+                  <!-- 最多打印 3 条,所以需要扣除优惠劵已打印的 -->
+                  <view
+                    v-for="item in getRewardActivityRuleItemDescriptions(
+                      state.rewardActivity,
+                    ).slice(0, 3 - state.couponInfo.slice(0, 1).length)"
+                    :key="item"
                     class="tag ss-m-r-10"
                     class="tag ss-m-r-10"
-                    v-for="coupon in state.couponInfo.slice(0, 1)"
-                    :key="coupon.id"
                     @tap="onOpenActivity"
                     @tap="onOpenActivity"
                   >
                   >
-                    222
-                  </view> -->
-									<view v-if="state.rewardActivity && state.rewardActivity.id > 0"
-										class="tag ss-m-r-10" @tap="onOpenActivity">
-										<text v-if="(state.rewardActivity.ruleDescriptions[0])[4]">券 </text>
-										{{(state.rewardActivity.ruleDescriptions[0])[1]}}
-									</view>
-									<view v-if="state.rewardActivity && state.rewardActivity.id > 0"
-										class="tag ss-m-r-10" @tap="onOpenActivity">
-										<text v-if="(state.rewardActivity.ruleDescriptions[0])[1]"></text>
-										{{(state.rewardActivity.ruleDescriptions[0])[1]}}
-									</view>
-								</view>
-							</div>
-							<!-- 领取优惠劵的按钮 -->
-							<view class="get-coupon-box ss-flex ss-col-center ss-m-l-20" @tap="onOpenActivity"
-								v-if="state.couponInfo.length">
-								<view class="discounts-title ss-m-r-8">领券</view>
-								<text class="cicon-forward"></text>
-							</view>
-						</view>
-						<view class="title-text ss-line-2 ss-m-b-6">{{ state.goodsInfo.name }}</view>
-						<view class="subtitle-text ss-line-1">{{ state.goodsInfo.introduction }}</view>
-					</view>
-
-					<!-- 功能卡片 -->
-					<view class="detail-cell-card detail-card ss-flex-col">
-						<detail-cell-sku v-model="state.selectedSku.goods_sku_text" :sku="state.selectedSku"
-							@tap="state.showSelectSku = true" />
-					</view>
-
-					<!-- 规格与数量弹框 -->
-					<s-select-sku :goodsInfo="state.goodsInfo" :show="state.showSelectSku" @addCart="onAddCart"
-						@buy="onBuy" @change="onSkuChange" @close="state.showSelectSku = false" />
-				</view>
-
-				<!-- 评价 -->
-				<detail-comment-card class="detail-comment-selector" :goodsId="state.goodsId" />
-				<!-- 详情 -->
-				<detail-content-card class="detail-content-selector" :content="state.goodsInfo.description" />
-
-				<!-- 活动跳转:拼团/秒杀/砍价活动 -->
-				<detail-activity-tip v-if="state.activityList.length > 0" :activity-list="state.activityList" />
-
-				<!-- 详情 tabbar -->
-				<detail-tabbar v-model="state.goodsInfo">
-					<view class="buy-box ss-flex ss-col-center ss-p-r-20" v-if="state.goodsInfo.stock > 0">
-						<button class="ss-reset-button add-btn ui-Shadow-Main" @tap="state.showSelectSku = true">
-							加入购物车
-						</button>
-						<button class="ss-reset-button buy-btn ui-Shadow-Main" @tap="state.showSelectSku = true">
-							立即购买
-						</button>
-					</view>
-					<view class="buy-box ss-flex ss-col-center ss-p-r-20" v-else>
-						<button class="ss-reset-button disabled-btn" disabled> 已售罄 </button>
-					</view>
-				</detail-tabbar>
-
-				<!-- 满减送/限时折扣活动弹窗 -->
-				<s-activity-pop v-model="state" :show="state.showActivityModel" @close="state.showActivityModel = false"
-					@get="onTakeCoupon" />
-			</block>
-		</s-layout>
-	</view>
+                    <text>{{ item }}</text>
+                  </view>
+                </view>
+              </div>
+              <!-- 领取优惠劵的按钮 -->
+              <view
+                class="get-coupon-box ss-flex ss-col-center ss-m-l-20"
+                @tap="onOpenActivity"
+                v-if="state.couponInfo.length"
+              >
+                <view class="discounts-title ss-m-r-8">领券</view>
+                <text class="cicon-forward"></text>
+              </view>
+            </view>
+            <view class="title-text ss-line-2 ss-m-b-6">{{ state.goodsInfo.name }}</view>
+            <view class="subtitle-text ss-line-1">{{ state.goodsInfo.introduction }}</view>
+          </view>
+
+          <!-- 功能卡片 -->
+          <view class="detail-cell-card detail-card ss-flex-col">
+            <detail-cell-sku
+              v-model="state.selectedSku.goods_sku_text"
+              :sku="state.selectedSku"
+              @tap="state.showSelectSku = true"
+            />
+          </view>
+
+          <!-- 规格与数量弹框 -->
+          <s-select-sku
+            :goodsInfo="state.goodsInfo"
+            :show="state.showSelectSku"
+            @addCart="onAddCart"
+            @buy="onBuy"
+            @change="onSkuChange"
+            @close="state.showSelectSku = false"
+          />
+        </view>
+
+        <!-- 评价 -->
+        <detail-comment-card class="detail-comment-selector" :goodsId="state.goodsId" />
+        <!-- 详情 -->
+        <detail-content-card
+          class="detail-content-selector"
+          :content="state.goodsInfo.description"
+        />
+
+        <!-- 活动跳转:拼团/秒杀/砍价活动 -->
+        <detail-activity-tip
+          v-if="state.activityList.length > 0"
+          :activity-list="state.activityList"
+        />
+
+        <!-- 详情 tabbar -->
+        <detail-tabbar v-model="state.goodsInfo">
+          <view class="buy-box ss-flex ss-col-center ss-p-r-20" v-if="state.goodsInfo.stock > 0">
+            <button
+              class="ss-reset-button add-btn ui-Shadow-Main"
+              @tap="state.showSelectSku = true"
+            >
+              加入购物车
+            </button>
+            <button
+              class="ss-reset-button buy-btn ui-Shadow-Main"
+              @tap="state.showSelectSku = true"
+            >
+              立即购买
+            </button>
+          </view>
+          <view class="buy-box ss-flex ss-col-center ss-p-r-20" v-else>
+            <button class="ss-reset-button disabled-btn" disabled> 已售罄 </button>
+          </view>
+        </detail-tabbar>
+
+        <!-- 满减送/限时折扣活动弹窗 -->
+        <s-activity-pop
+          v-model="state"
+          :show="state.showActivityModel"
+          @close="state.showActivityModel = false"
+          @get="onTakeCoupon"
+        />
+      </block>
+    </s-layout>
+  </view>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-	import {
-		reactive,
-		computed,
-		ref,
-		toRaw
-	} from 'vue';
-	import {
-		onLoad,
-		onPageScroll
-	} from '@dcloudio/uni-app';
-	import sheep from '@/sheep';
-	import CouponApi from '@/sheep/api/promotion/coupon';
-	import ActivityApi from '@/sheep/api/promotion/activity';
-	import FavoriteApi from '@/sheep/api/product/favorite';
-	import RewardActivityApi from '@/sheep/api/promotion/rewardActivity';
-	import {
-		formatSales,
-		formatGoodsSwiper,
-		fen2yuan
-	} from '@/sheep/hooks/useGoods';
-	import detailNavbar from './components/detail/detail-navbar.vue';
-	import detailCellSku from './components/detail/detail-cell-sku.vue';
-	import detailTabbar from './components/detail/detail-tabbar.vue';
-	import detailSkeleton from './components/detail/detail-skeleton.vue';
-	import detailCommentCard from './components/detail/detail-comment-card.vue';
-	import detailContentCard from './components/detail/detail-content-card.vue';
-	import detailActivityTip from './components/detail/detail-activity-tip.vue';
-	import {
-		isEmpty
-	} from 'lodash-es';
-	import SpuApi from '@/sheep/api/product/spu';
-
-	onPageScroll(() => {});
-	import countDown from '@/sheep/components/countDown/index.vue';
-	import OrderApi from '@/sheep/api/trade/order';
-
-	const bgColor = {
-		bgColor: '#E93323',
-		Color: '#fff',
-		width: '44rpx',
-		timeTxtwidth: '16rpx',
-		isDay: true,
-	};
-	const isLogin = computed(() => sheep.$store('user').isLogin);
-	const state = reactive({
-		goodsId: 0,
-		skeletonLoading: true, // SPU 加载中
-		goodsInfo: {}, // SPU 信息
-		showSelectSku: false, // 是否展示 SKU 选择弹窗
-		selectedSku: {}, // 选中的 SKU
-		settlementSku: {}, // 结算的 SKU:由于 selectedSku 不进行默认选中,所以初始使用结算价格最低的 SKU 作为基础展示
-		showModel: false, // 是否展示 Coupon 优惠劵的弹窗
-		couponInfo: [], // 可领取的 Coupon 优惠劵的列表
-		showActivityModel: false, // 【满减送/限时折扣】是否展示 Activity 营销活动的弹窗
-		rewardActivity: {}, // 【满减送】活动
-		activityList: [], // 【秒杀/拼团/砍价】可参与的 Activity 营销活动的列表
-	});
-
-	// 规格变更
-	function onSkuChange(e) {
-		state.selectedSku = e;
-		state.settlementSku = e;
-	}
-
-	// 添加购物车
-	function onAddCart(e) {
-		if (!e.id) {
-			sheep.$helper.toast('请选择商品规格');
-			return;
-		}
-		sheep.$store('cart').add(e);
-	}
-
-	// 立即购买
-	function onBuy(e) {
-		if (!e.id) {
-			sheep.$helper.toast('请选择商品规格');
-			return;
-		}
-		sheep.$router.go('/pages/order/confirm', {
-			data: JSON.stringify({
-				items: [{
-					skuId: e.id,
-					count: e.goods_num,
-					categoryId: state.goodsInfo.categoryId,
-				}, ],
-			}),
-		});
-	}
-
-	// 打开营销弹窗
-	function onOpenActivity() {
-		state.showActivityModel = true;
-	}
-
-	// 立即领取优惠劵
-	async function onTakeCoupon(id) {
-		const {
-			code
-		} = await CouponApi.takeCoupon(id);
-		if (code !== 0) {
-			return;
-		}
-		uni.showToast({
-			title: '领取成功',
-		});
-		setTimeout(() => {
-			getCoupon();
-		}, 1000);
-	}
-
-	const shareInfo = computed(() => {
-		if (isEmpty(state.goodsInfo)) return {};
-		return sheep.$platform.share.getShareInfo({
-			title: state.goodsInfo.name,
-			image: sheep.$url.cdn(state.goodsInfo.picUrl),
-			desc: state.goodsInfo.introduction,
-			params: {
-				page: '2',
-				query: state.goodsInfo.id,
-			},
-		}, {
-			type: 'goods', // 商品海报
-			title: state.goodsInfo.name, // 商品名称
-			image: sheep.$url.cdn(state.goodsInfo.picUrl), // 商品主图
-			price: fen2yuan(state.goodsInfo.price), // 商品价格
-			original_price: fen2yuan(state.goodsInfo.marketPrice), // 商品原价
-		}, );
-	});
-
-	async function getCoupon() {
-		const {
-			code,
-			data
-		} = await CouponApi.getCouponTemplateList(state.goodsId, 2, 10);
-		if (code === 0) {
-			state.couponInfo = data;
-		}
-	}
-
-	async function getSettlementByIds(ids) {
-		let {
-			data,
-			code
-		} = await OrderApi.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;
-			//获取活动时间
-			getActivityTime(state.rewardActivity.id)
-		}
-	}
-
-	//获取活动时间
-	async function getActivityTime(id) {
-		const {
-			code,
-			data
-		} = await RewardActivityApi.getRewardActivity(id);
-		if (code === 0) {
-			// console.log('获取到的活动 数据', data)
-			state.rewardActivity.startTime = data.startTime
-			state.rewardActivity.endTime = data.endTime
-		}
-	}
-	 onLoad((options) => {
-		// 非法参数
-		if (!options.id) {
-			state.goodsInfo = null;
-			return;
-		}
-		state.goodsId = options.id;
-		// 1. 加载商品信息
-		SpuApi.getSpuDetail(state.goodsId).then((res) => {
-			// 未找到商品
-			if (res.code !== 0 || !res.data) {
-				state.goodsInfo = null;
-				return;
-			}
-			// 加载到商品
-			state.skeletonLoading = false;
-			state.goodsInfo = res.data;
-			// 加载是否收藏
-			if (isLogin.value) {
-				FavoriteApi.isFavoriteExists(state.goodsId, 'goods').then((res) => {
-					if (res.code !== 0) {
-						return;
-					}
-					state.goodsInfo.favorite = res.data;
-				});
-			}
-		});
-
-		// 2. 加载优惠劵信息
-		getCoupon();
-
-		// 3. 加载营销活动信息
-		ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => {
-			if (res.code !== 0) {
-				return;
-			}
-			state.activityList = res.data;
-		});
-		//获取结算信息
-		getSettlementByIds(state.goodsId);
-	});
+  import { reactive, computed, ref, toRaw } from 'vue';
+  import { onLoad, onPageScroll } from '@dcloudio/uni-app';
+  import sheep from '@/sheep';
+  import CouponApi from '@/sheep/api/promotion/coupon';
+  import ActivityApi from '@/sheep/api/promotion/activity';
+  import FavoriteApi from '@/sheep/api/product/favorite';
+  import RewardActivityApi from '@/sheep/api/promotion/rewardActivity';
+  import {
+    formatSales,
+    formatGoodsSwiper,
+    fen2yuan,
+    fen2yuanSimple,
+    formatDiscountPercent,
+    getRewardActivityRuleItemDescriptions,
+  } from '@/sheep/hooks/useGoods';
+  import detailNavbar from './components/detail/detail-navbar.vue';
+  import detailCellSku from './components/detail/detail-cell-sku.vue';
+  import detailTabbar from './components/detail/detail-tabbar.vue';
+  import detailSkeleton from './components/detail/detail-skeleton.vue';
+  import detailCommentCard from './components/detail/detail-comment-card.vue';
+  import detailContentCard from './components/detail/detail-content-card.vue';
+  import detailActivityTip from './components/detail/detail-activity-tip.vue';
+  import { isEmpty } from 'lodash-es';
+  import SpuApi from '@/sheep/api/product/spu';
+
+  onPageScroll(() => {});
+  import countDown from '@/sheep/components/countDown/index.vue';
+  import OrderApi from '@/sheep/api/trade/order';
+  import activity from '@/sheep/api/promotion/activity';
+
+  const bgColor = {
+    bgColor: '#E93323',
+    Color: '#fff',
+    width: '44rpx',
+    timeTxtwidth: '16rpx',
+    isDay: true,
+  };
+  const isLogin = computed(() => sheep.$store('user').isLogin);
+  const state = reactive({
+    goodsId: 0,
+    skeletonLoading: true, // SPU 加载中
+    goodsInfo: {}, // SPU 信息
+    showSelectSku: false, // 是否展示 SKU 选择弹窗
+    selectedSku: {}, // 选中的 SKU
+    settlementSku: {}, // 结算的 SKU:由于 selectedSku 不进行默认选中,所以初始使用结算价格最低的 SKU 作为基础展示
+    showModel: false, // 是否展示 Coupon 优惠劵的弹窗
+    couponInfo: [], // 可领取的 Coupon 优惠劵的列表
+    showActivityModel: false, // 【满减送/限时折扣】是否展示 Activity 营销活动的弹窗
+    rewardActivity: {}, // 【满减送】活动
+    activityList: [], // 【秒杀/拼团/砍价】可参与的 Activity 营销活动的列表
+  });
+
+  // 规格变更
+  function onSkuChange(e) {
+    state.selectedSku = e;
+    state.settlementSku = e;
+  }
+
+  // 添加购物车
+  function onAddCart(e) {
+    if (!e.id) {
+      sheep.$helper.toast('请选择商品规格');
+      return;
+    }
+    sheep.$store('cart').add(e);
+  }
+
+  // 立即购买
+  function onBuy(e) {
+    if (!e.id) {
+      sheep.$helper.toast('请选择商品规格');
+      return;
+    }
+    sheep.$router.go('/pages/order/confirm', {
+      data: JSON.stringify({
+        items: [
+          {
+            skuId: e.id,
+            count: e.goods_num,
+            categoryId: state.goodsInfo.categoryId,
+          },
+        ],
+      }),
+    });
+  }
+
+  // 打开营销弹窗
+  function onOpenActivity() {
+    state.showActivityModel = true;
+  }
+
+  // 立即领取优惠劵
+  async function onTakeCoupon(id) {
+    const { code } = await CouponApi.takeCoupon(id);
+    if (code !== 0) {
+      return;
+    }
+    uni.showToast({
+      title: '领取成功',
+    });
+    setTimeout(() => {
+      getCoupon();
+    }, 1000);
+  }
+
+  const shareInfo = computed(() => {
+    if (isEmpty(state.goodsInfo)) return {};
+    return sheep.$platform.share.getShareInfo(
+      {
+        title: state.goodsInfo.name,
+        image: sheep.$url.cdn(state.goodsInfo.picUrl),
+        desc: state.goodsInfo.introduction,
+        params: {
+          page: '2',
+          query: state.goodsInfo.id,
+        },
+      },
+      {
+        type: 'goods', // 商品海报
+        title: state.goodsInfo.name, // 商品名称
+        image: sheep.$url.cdn(state.goodsInfo.picUrl), // 商品主图
+        price: fen2yuan(state.goodsInfo.price), // 商品价格
+        original_price: fen2yuan(state.goodsInfo.marketPrice), // 商品原价
+      },
+    );
+  });
+
+  async function getCoupon() {
+    const { code, data } = await CouponApi.getCouponTemplateList(state.goodsId, 2, 10);
+    if (code === 0) {
+      state.couponInfo = data;
+    }
+  }
+
+  async function getSettlementByIds(ids) {
+    let { data, code } = await OrderApi.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;
+      //获取活动时间
+      getActivityTime(state.rewardActivity.id);
+    }
+  }
+
+  //获取活动时间
+  async function getActivityTime(id) {
+    const { code, data } = await RewardActivityApi.getRewardActivity(id);
+    if (code === 0) {
+      // console.log('获取到的活动 数据', data)
+      state.rewardActivity.startTime = data.startTime;
+      state.rewardActivity.endTime = data.endTime;
+    }
+  }
+
+  onLoad((options) => {
+    // 非法参数
+    if (!options.id) {
+      state.goodsInfo = null;
+      return;
+    }
+    state.goodsId = options.id;
+    // 1. 加载商品信息
+    SpuApi.getSpuDetail(state.goodsId).then((res) => {
+      // 未找到商品
+      if (res.code !== 0 || !res.data) {
+        state.goodsInfo = null;
+        return;
+      }
+      // 加载到商品
+      state.skeletonLoading = false;
+      state.goodsInfo = res.data;
+      // 加载是否收藏
+      if (isLogin.value) {
+        FavoriteApi.isFavoriteExists(state.goodsId, 'goods').then((res) => {
+          if (res.code !== 0) {
+            return;
+          }
+          state.goodsInfo.favorite = res.data;
+        });
+      }
+    });
+
+    // 2. 加载优惠劵信息
+    getCoupon();
+
+    // 3. 加载营销活动信息
+    ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => {
+      if (res.code !== 0) {
+        return;
+      }
+      state.activityList = res.data;
+    });
+    //获取结算信息
+    getSettlementByIds(state.goodsId);
+  });
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-	.detail-card {
-		background-color: #ffff;
-		margin: 14rpx 20rpx;
-		border-radius: 10rpx;
-		overflow: hidden;
-	}
-
-	// 价格标题卡片
-	.title-card {
-		.price-box {
-			.price-text {
-				font-size: 42rpx;
-				font-weight: 500;
-				color: #ff3000;
-				line-height: 30rpx;
-				font-family: OPPOSANS;
-
-				&::before {
-					content: '¥';
-					font-size: 30rpx;
-				}
-			}
-
-			.origin-price-text {
-				font-size: 26rpx;
-				font-weight: 400;
-				text-decoration: line-through;
-				color: $gray-c;
-				font-family: OPPOSANS;
-
-				&::before {
-					content: '¥';
-				}
-			}
-		}
-
-		.sales-text {
-			font-size: 26rpx;
-			font-weight: 500;
-			color: $gray-c;
-		}
-
-		.discounts-box {
-			.tag-content {
-				flex: 1;
-				min-width: 0;
-				white-space: nowrap;
-			}
-
-			.tag-box {
-				overflow: hidden;
-				text-overflow: ellipsis;
-			}
-
-			.tag {
-				flex-shrink: 0;
-				padding: 4rpx 10rpx;
-				font-size: 24rpx;
-				font-weight: 500;
-				border-radius: 4rpx;
-				color: var(--ui-BG-Main);
-				background: var(--ui-BG-Main-tag);
-			}
-
-			.discounts-title {
-				font-size: 24rpx;
-				font-weight: 500;
-				color: var(--ui-BG-Main);
-				line-height: normal;
-			}
-
-			.cicon-forward {
-				color: var(--ui-BG-Main);
-				font-size: 24rpx;
-				line-height: normal;
-				margin-top: 4rpx;
-			}
-		}
-
-		.title-text {
-			font-size: 30rpx;
-			font-weight: bold;
-			line-height: 42rpx;
-		}
-
-		.subtitle-text {
-			font-size: 26rpx;
-			font-weight: 400;
-			color: $dark-9;
-			line-height: 42rpx;
-		}
-	}
-
-	// 购买
-	.buy-box {
-		.add-btn {
-			width: 214rpx;
-			height: 72rpx;
-			font-weight: 500;
-			font-size: 28rpx;
-			border-radius: 40rpx 0 0 40rpx;
-			background-color: var(--ui-BG-Main-light);
-			color: var(--ui-BG-Main);
-		}
-
-		.buy-btn {
-			width: 214rpx;
-			height: 72rpx;
-			font-weight: 500;
-			font-size: 28rpx;
-
-			border-radius: 0 40rpx 40rpx 0;
-			background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
-			color: $white;
-		}
-
-		.disabled-btn {
-			width: 428rpx;
-			height: 72rpx;
-			border-radius: 40rpx;
-			background: #999999;
-			color: $white;
-		}
-	}
-
-	.model-box {
-		height: 60vh;
-
-		.model-content {
-			height: 56vh;
-		}
-
-		.title {
-			font-size: 36rpx;
-			font-weight: bold;
-			color: #333333;
-		}
-
-		.subtitle {
-			font-size: 26rpx;
-			font-weight: 500;
-			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>
+  .detail-card {
+    background-color: #ffff;
+    margin: 14rpx 20rpx;
+    border-radius: 10rpx;
+    overflow: hidden;
+  }
+
+  // 价格标题卡片
+  .title-card {
+    .price-box {
+      .price-text {
+        font-size: 42rpx;
+        font-weight: 500;
+        color: #ff3000;
+        line-height: 30rpx;
+        font-family: OPPOSANS;
+
+        &::before {
+          content: '¥';
+          font-size: 30rpx;
+        }
+      }
+
+      .origin-price-text {
+        font-size: 26rpx;
+        font-weight: 400;
+        text-decoration: line-through;
+        color: $gray-c;
+        font-family: OPPOSANS;
+
+        &::before {
+          content: '¥';
+        }
+      }
+    }
+
+    .sales-text {
+      font-size: 26rpx;
+      font-weight: 500;
+      color: $gray-c;
+    }
+
+    .discounts-box {
+      .tag-content {
+        flex: 1;
+        min-width: 0;
+        white-space: nowrap;
+      }
+
+      .tag-box {
+        overflow: hidden;
+        text-overflow: ellipsis;
+      }
+
+      .tag {
+        flex-shrink: 0;
+        padding: 4rpx 10rpx;
+        font-size: 24rpx;
+        font-weight: 500;
+        border-radius: 4rpx;
+        color: var(--ui-BG-Main);
+        background: var(--ui-BG-Main-tag);
+      }
+
+      .discounts-title {
+        font-size: 24rpx;
+        font-weight: 500;
+        color: var(--ui-BG-Main);
+        line-height: normal;
+      }
+
+      .cicon-forward {
+        color: var(--ui-BG-Main);
+        font-size: 24rpx;
+        line-height: normal;
+        margin-top: 4rpx;
+      }
+    }
+
+    .title-text {
+      font-size: 30rpx;
+      font-weight: bold;
+      line-height: 42rpx;
+    }
+
+    .subtitle-text {
+      font-size: 26rpx;
+      font-weight: 400;
+      color: $dark-9;
+      line-height: 42rpx;
+    }
+  }
+
+  // 购买
+  .buy-box {
+    .add-btn {
+      width: 214rpx;
+      height: 72rpx;
+      font-weight: 500;
+      font-size: 28rpx;
+      border-radius: 40rpx 0 0 40rpx;
+      background-color: var(--ui-BG-Main-light);
+      color: var(--ui-BG-Main);
+    }
+
+    .buy-btn {
+      width: 214rpx;
+      height: 72rpx;
+      font-weight: 500;
+      font-size: 28rpx;
+
+      border-radius: 0 40rpx 40rpx 0;
+      background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
+      color: $white;
+    }
+
+    .disabled-btn {
+      width: 428rpx;
+      height: 72rpx;
+      border-radius: 40rpx;
+      background: #999999;
+      color: $white;
+    }
+  }
+
+  .model-box {
+    height: 60vh;
+
+    .model-content {
+      height: 56vh;
+    }
+
+    .title {
+      font-size: 36rpx;
+      font-weight: bold;
+      color: #333333;
+    }
+
+    .subtitle {
+      font-size: 26rpx;
+      font-weight: 500;
+      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>

+ 249 - 253
sheep/components/s-activity-pop/s-activity-pop.vue

@@ -1,259 +1,255 @@
 <!-- 商品信息:满减送等营销活动的弹窗 -->
 <!-- 商品信息:满减送等营销活动的弹窗 -->
 <template>
 <template>
-	<su-popup :show="show" type="bottom" round="20" @close="emits('close')" showClose>
-		<view class="model-box">
-			<view class="title ss-m-t-16 ss-m-l-20 ss-flex">优惠</view>
-			<view v-if="state.rewardActivity && state.rewardActivity.id > 0">
-				<view class="titleLi">促销</view>
-				<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.handeActivity" :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">{{item.name}}</view>
-							<view class="model-content-title">
-								<view class="contBu">
-									<text v-for="(items,indexs) in item.value" :key="indexs">{{ items }};</text>
-								</view>
-								<view class="ss-m-b-24 cotBu-txt">
-									{{ sheep.$helper.timeFormat(state.rewardActivity.startTime, 'yyyy.mm.dd') }}
-									-
-									{{ sheep.$helper.timeFormat(state.rewardActivity.endTime, 'yyyy.mm.dd') }}
-								</view>
-							</view>
-							<text class="cicon-forward" />
-						</view>
-					</view>
-				</scroll-view>
-			</view>
-			<view class="titleLi">可领优惠券</view>
-			<scroll-view class="model-content" scroll-y :scroll-with-animation="false" :enable-back-to-top="true" v-if="state.couponInfo.length">
-				<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="model-content-tag2">
-							<view class="usePrice"> ¥{{ fen2yuan(item.discountPrice) }} </view>
-							<view class="impose"> 满¥{{ fen2yuan(item.usePrice) }}可用 </view>
-						</view>
-						<view class="model-content-title2">
-							<view class="contBu">
-								{{ item.name }}
-							</view>
-							<view class="ss-m-b-24 cotBu-txt">
-								{{
-		              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 class="coupon" @click.stop="getBuy(item.id)" v-if="item.canTake"> 立即领取 </view>
-						<view class="coupon2" v-else> 已领取 </view>
-					</view>
-				</view>
-			</scroll-view>
-			<view class="nullBox" v-else>
-				暂无可领优惠券
-			</view>
-		</view>
-	</su-popup>
+  <su-popup :show="show" type="bottom" round="20" @close="emits('close')" showClose>
+    <view class="model-box">
+      <view class="title ss-m-t-16 ss-m-l-20 ss-flex">优惠</view>
+      <view v-if="state.rewardActivity && state.rewardActivity.id > 0">
+        <view class="titleLi">促销</view>
+        <scroll-view
+          class="model-content"
+          scroll-y
+          :scroll-with-animation="false"
+          :enable-back-to-top="true"
+        >
+          <view
+            class="actBox"
+            v-for="(item, index) in getRewardActivityRuleGroupDescriptions(state.rewardActivity)"
+            :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">{{ item.name }}</view>
+              <view class="model-content-title">
+                <view class="contBu">
+                  {{ item.values.join(';') }}
+                </view>
+                <view class="ss-m-b-24 cotBu-txt">
+                  {{ sheep.$helper.timeFormat(state.rewardActivity.startTime, 'yyyy.mm.dd') }}
+                  -
+                  {{ sheep.$helper.timeFormat(state.rewardActivity.endTime, 'yyyy.mm.dd') }}
+                </view>
+              </view>
+              <text class="cicon-forward" />
+            </view>
+          </view>
+        </scroll-view>
+      </view>
+      <view class="titleLi">可领优惠券</view>
+      <scroll-view
+        class="model-content"
+        scroll-y
+        :scroll-with-animation="false"
+        :enable-back-to-top="true"
+        v-if="state.couponInfo.length"
+      >
+        <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="model-content-tag2">
+              <view class="usePrice"> ¥{{ fen2yuan(item.discountPrice) }} </view>
+              <view class="impose"> 满¥{{ fen2yuan(item.usePrice) }}可用 </view>
+            </view>
+            <view class="model-content-title2">
+              <view class="contBu">
+                {{ item.name }}
+              </view>
+              <view class="ss-m-b-24 cotBu-txt">
+                {{
+                  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 class="coupon" @click.stop="getBuy(item.id)" v-if="item.canTake"> 立即领取 </view>
+            <view class="coupon2" v-else> 已领取 </view>
+          </view>
+        </view>
+      </scroll-view>
+      <view class="nullBox" v-else> 暂无可领优惠券 </view>
+    </view>
+  </su-popup>
 </template>
 </template>
 <script setup>
 <script setup>
-	import sheep from '@/sheep';
-	import {
-		handeleData
-	} from '@/sheep/hooks/useGoods';
-	import {
-		computed,
-		reactive,
-		watch,
-		ref
-	} from 'vue';
-	import {
-		fen2yuan
-	} from '@/sheep/hooks/useGoods';
-	const props = defineProps({
-		modelValue: {
-			type: Object,
-			default () {},
-		},
-		show: {
-			type: Boolean,
-			default: false,
-		},
-	});
-	const emits = defineEmits(['close']);
-	const state = reactive({
-		rewardActivity: computed(() => props.modelValue.rewardActivity),
-		couponInfo: computed(() => props.modelValue.couponInfo),
-	});
-	// setTimeout(()=>{
-	// 	 console.log('历程数据',state.rewardActivity.ruleDescriptions)
-	// 	 console.log('处理数据',handeleData(props.modelValue.rewardActivity.ruleDescriptions))
-	// },5000)
-	// 领取优惠劵
-	const getBuy = (id) => {
-		emits('get', id);
-	};
-
-	function onGoodsList(e) {
-		sheep.$router.go('/pages/activity/index', {
-			activityId: e.id,
-		});
-	}
-	//监听获取到数据后再执行且只执行一次
-	let flag = ref(true)
-	watch(state, (newValue, oldValue) => {
-		if (flag.value) {
-			flag.value = false
-			state.handeActivity = handeleData(state.rewardActivity.ruleDescriptions)
-		}
-	});
+  import sheep from '@/sheep';
+  import { getRewardActivityRuleGroupDescriptions } from '@/sheep/hooks/useGoods';
+  import { computed, reactive, watch, ref } from 'vue';
+  import { fen2yuan } from '@/sheep/hooks/useGoods';
+  const props = defineProps({
+    modelValue: {
+      type: Object,
+      default() {},
+    },
+    show: {
+      type: Boolean,
+      default: false,
+    },
+  });
+  const emits = defineEmits(['close']);
+  const state = reactive({
+    rewardActivity: computed(() => props.modelValue.rewardActivity),
+    couponInfo: computed(() => props.modelValue.couponInfo),
+  });
+
+  // 领取优惠劵
+  const getBuy = (id) => {
+    emits('get', id);
+  };
+
+  function onGoodsList(e) {
+    sheep.$router.go('/pages/activity/index', {
+      activityId: e.id,
+    });
+  }
 </script>
 </script>
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-	.model-box {
-		height: 60vh;
-
-		.title {
-			justify-content: center;
-			font-size: 36rpx;
-			height: 80rpx;
-			font-weight: bold;
-			color: #333333;
-		}
-	}
-
-	.model-content {
-		height: fit-content;
-		max-height: 380rpx;
-		padding: 0 20rpx;
-		box-sizing: border-box;
-		margin-top: 20rpx;
-
-		.model-content-tag {
-			// background: rgba(#ff6911, 0.1);
-			font-size: 35rpx;
-			font-weight: 500;
-			color: #ff6911;
-			line-height: 150rpx;
-			width: 200rpx;
-			height: 150rpx;
-			text-align: center;
-
-			// border-radius: 5rpx;
-		}
-
-		.model-content-title {
-			width: 450rpx;
-			height: 150rpx;
-			font-size: 26rpx;
-			font-weight: 500;
-			color: #333333;
-			overflow: hidden;
-		}
-
-		.cicon-forward {
-			font-size: 28rpx;
-			color: #999999;
-			margin: 0 auto;
-		}
-	}
-
-	// 新增的
-	.titleLi {
-		margin: 10rpx 0 10rpx 20rpx;
-		font-size: 26rpx;
-	}
-
-	.actBox {
-		width: 700rpx;
-		height: 150rpx;
-		background-color: #fff2f2;
-		margin: 10rpx auto;
-		border-radius: 10rpx;
-	}
-
-	.boxCont {
-		width: 700rpx;
-		height: 150rpx;
-		align-items: center;
-	}
-
-	.contBu {
-		height: 80rpx;
-		line-height: 80rpx;
-		overflow: hidden;
-		font-size: 30rpx;
-		white-space: nowrap;
-		text-overflow: ellipsis;
-		-o-text-overflow: ellipsis;
-	}
-
-	.cotBu-txt {
-		height: 70rpx;
-		line-height: 70rpx;
-		font-size: 25rpx;
-		color: #999999;
-	}
-
-	.model-content-tag2 {
-		font-size: 35rpx;
-		font-weight: 500;
-		color: #ff6911;
-		width: 200rpx;
-		height: 150rpx;
-		text-align: center;
-	}
-
-	.usePrice {
-		width: 200rpx;
-		height: 90rpx;
-		line-height: 100rpx;
-		// background-color: red;
-	}
-
-	.impose {
-		width: 200rpx;
-		height: 50rpx;
-		// line-height: 75rpx;
-		font-size: 23rpx;
-		// background-color: gold;
-	}
-
-	.model-content-title2 {
-		width: 330rpx;
-		height: 150rpx;
-		font-size: 26rpx;
-		font-weight: 500;
-		color: #333333;
-		overflow: hidden;
-	}
-
-	.coupon {
-		width: 150rpx;
-		height: 50rpx;
-		line-height: 50rpx;
-		background-color: rgb(255, 68, 68);
-		color: white;
-		border-radius: 30rpx;
-		text-align: center;
-		font-size: 25rpx;
-	}
-
-	.coupon2 {
-		width: 150rpx;
-		height: 50rpx;
-		line-height: 50rpx;
-		background-color: rgb(203, 192, 191);
-		color: white;
-		border-radius: 30rpx;
-		text-align: center;
-		font-size: 25rpx;
-	}
-	.nullBox{
-		width: 100%;
-		height: 300rpx;
-		font-size: 25rpx;
-		line-height: 300rpx;
-		text-align: center;
-		color: #999999;
-	}
-</style>
+  .model-box {
+    height: 60vh;
+
+    .title {
+      justify-content: center;
+      font-size: 36rpx;
+      height: 80rpx;
+      font-weight: bold;
+      color: #333333;
+    }
+  }
+
+  .model-content {
+    height: fit-content;
+    max-height: 380rpx;
+    padding: 0 20rpx;
+    box-sizing: border-box;
+    margin-top: 20rpx;
+
+    .model-content-tag {
+      // background: rgba(#ff6911, 0.1);
+      font-size: 35rpx;
+      font-weight: 500;
+      color: #ff6911;
+      line-height: 150rpx;
+      width: 200rpx;
+      height: 150rpx;
+      text-align: center;
+
+      // border-radius: 5rpx;
+    }
+
+    .model-content-title {
+      width: 450rpx;
+      height: 150rpx;
+      font-size: 26rpx;
+      font-weight: 500;
+      color: #333333;
+      overflow: hidden;
+    }
+
+    .cicon-forward {
+      font-size: 28rpx;
+      color: #999999;
+      margin: 0 auto;
+    }
+  }
+
+  // 新增的
+  .titleLi {
+    margin: 10rpx 0 10rpx 20rpx;
+    font-size: 26rpx;
+  }
+
+  .actBox {
+    width: 700rpx;
+    height: 150rpx;
+    background-color: #fff2f2;
+    margin: 10rpx auto;
+    border-radius: 10rpx;
+  }
+
+  .boxCont {
+    width: 700rpx;
+    height: 150rpx;
+    align-items: center;
+  }
+
+  .contBu {
+    height: 80rpx;
+    line-height: 80rpx;
+    overflow: hidden;
+    font-size: 30rpx;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    -o-text-overflow: ellipsis;
+  }
+
+  .cotBu-txt {
+    height: 70rpx;
+    line-height: 70rpx;
+    font-size: 25rpx;
+    color: #999999;
+  }
+
+  .model-content-tag2 {
+    font-size: 35rpx;
+    font-weight: 500;
+    color: #ff6911;
+    width: 200rpx;
+    height: 150rpx;
+    text-align: center;
+  }
+
+  .usePrice {
+    width: 200rpx;
+    height: 90rpx;
+    line-height: 100rpx;
+    // background-color: red;
+  }
+
+  .impose {
+    width: 200rpx;
+    height: 50rpx;
+    // line-height: 75rpx;
+    font-size: 23rpx;
+    // background-color: gold;
+  }
+
+  .model-content-title2 {
+    width: 330rpx;
+    height: 150rpx;
+    font-size: 26rpx;
+    font-weight: 500;
+    color: #333333;
+    overflow: hidden;
+  }
+
+  .coupon {
+    width: 150rpx;
+    height: 50rpx;
+    line-height: 50rpx;
+    background-color: rgb(255, 68, 68);
+    color: white;
+    border-radius: 30rpx;
+    text-align: center;
+    font-size: 25rpx;
+  }
+
+  .coupon2 {
+    width: 150rpx;
+    height: 50rpx;
+    line-height: 50rpx;
+    background-color: rgb(203, 192, 191);
+    color: white;
+    border-radius: 30rpx;
+    text-align: center;
+    font-size: 25rpx;
+  }
+  .nullBox {
+    width: 100%;
+    height: 300rpx;
+    font-size: 25rpx;
+    line-height: 300rpx;
+    text-align: center;
+    color: #999999;
+  }
+</style>

+ 871 - 795
sheep/components/s-goods-column/s-goods-column.vue

@@ -1,809 +1,885 @@
 <!-- 页面 -->
 <!-- 页面 -->
 <template>
 <template>
-	<view class="ss-goods-wrap">
-		<!-- xs卡片:横向紧凑型,一行放两个,图片左内容右边  -->
-		<view v-if="size === 'xs'" class="xs-goods-card ss-flex ss-col-stretch" :style="[elStyles]" @tap="onClick">
-			<view v-if="tagStyle.show" class="tag-icon-box">
-				<image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
-			</view>
-			<image class="xs-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="aspectFit" />
-			<view v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show"
-				class="xs-goods-content ss-flex-col ss-row-around">
-				<view v-if="goodsFields.title?.show || goodsFields.name?.show" class="xs-goods-title ss-line-1"
-					:style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]">
-					{{ data.title || data.name }}
-				</view>
-				<!-- 活动信息 -->
-				<view class="iconBox" v-if="data.promotionType > 0 || data.rewardActivity">
-					<view class="card" v-if="discountText">{{ discountText }}</view>
-					<view class="card2" v-if="data.rewardActivity">
-						{{ (data.rewardActivity.ruleDescriptions[0])[1] }}
-					</view>
-					<view class="card2" v-if="data.rewardActivity && (data.rewardActivity.ruleDescriptions[0])[3]">
-						{{ (data.rewardActivity.ruleDescriptions[0])[3] }}
-					</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>
-					<!-- 活动价格 -->
-					<text v-if="data.promotionPrice > 0">{{ fen2yuan(data.promotionPrice) }}</text>
-					<text v-else>
-						{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
-					</text>
-				</view>
-			</view>
-		</view>
-
-		<!-- sm卡片:竖向紧凑,一行放三个,图上内容下 -->
-		<view v-if="size === 'sm'" class="sm-goods-card ss-flex-col" :style="[elStyles]" @tap="onClick">
-			<view v-if="tagStyle.show" class="tag-icon-box">
-				<image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
-			</view>
-			<image class="sm-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="aspectFill"></image>
-
-			<view v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show"
-				class="sm-goods-content" :style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]">
-				<view v-if="goodsFields.title?.show || goodsFields.name?.show"
-					class="sm-goods-title ss-line-1 ss-m-b-16">
-					{{ data.title || data.name }}
-				</view>
-				<!-- 活动信息 -->
-				<view class="iconBox" v-if="data.promotionType > 0 || data.rewardActivity">
-					<view class="card" v-if="discountText">{{ discountText }}</view>
-					<view class="card2" v-if="data.rewardActivity">
-						{{ (data.rewardActivity.ruleDescriptions[0])[1] }}
-					</view>
-					<view class="card2" v-if="data.rewardActivity && (data.rewardActivity.ruleDescriptions[0])[3]">
-						{{ (data.rewardActivity.ruleDescriptions[0])[3] }}
-					</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>
-					<!-- 活动价格 -->
-					<text v-if="data.promotionPrice > 0">{{ fen2yuan(data.promotionPrice) }}</text>
-					<text v-else>
-						{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
-					</text>
-				</view>
-			</view>
-		</view>
-
-		<!-- md卡片:竖向,一行放两个,图上内容下 -->
-		<view v-if="size === 'md'" class="md-goods-card ss-flex-col" :style="[elStyles]" @tap="onClick">
-			<view v-if="tagStyle.show" class="tag-icon-box">
-				<image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)" />
-			</view>
-			<image class="md-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="widthFix" />
-			<view class="md-goods-content ss-flex-col ss-row-around ss-p-b-20 ss-p-t-20 ss-p-x-16" :id="elId">
-				<view v-if="goodsFields.title?.show || goodsFields.name?.show" class="md-goods-title ss-line-1"
-					:style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]">
-					{{ data.title || data.name }}
-				</view>
-				<view v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
-					class="md-goods-subtitle ss-m-t-16 ss-line-1"
-					:style="[{ color: subTitleColor, background: subTitleBackground }]">
-					{{ data.subtitle || data.introduction }}
-				</view>
-				<slot name="activity">
-					<view v-if="data.promos?.length" class="tag-box ss-flex-wrap ss-flex ss-col-center">
-						<view class="activity-tag ss-m-r-10 ss-m-t-16" v-for="item in data.promos" :key="item.id">
-							{{ item.title }}
-						</view>
-					</view>
-				</slot>
-				<!-- 活动信息 -->
-				<view class="iconBox" v-if="data.promotionType > 0 || data.rewardActivity">
-					<view class="card" v-if="discountText">{{ discountText }}</view>
-					<view class="card2" v-if="data.rewardActivity">
-						{{ (data.rewardActivity.ruleDescriptions[0])[1] }}
-					</view>
-					<view class="card2" v-if="data.rewardActivity && (data.rewardActivity.ruleDescriptions[0])[3]">
-						{{ (data.rewardActivity.ruleDescriptions[0])[3] }}
-					</view>
-				</view>
-				<view class="ss-flex ss-col-bottom">
-					<view v-if="goodsFields.price?.show" class="md-goods-price ss-m-t-16 font-OPPOSANS ss-m-r-10"
-						:style="[{ color: goodsFields.price.color }]">
-						<text class="price-unit ss-font-24">{{ priceUnit }}</text>
-						<!-- 活动价格 -->
-						<text v-if="data.promotionPrice > 0">{{ fen2yuan(data.promotionPrice) }}</text>
-						<text v-else>
-							{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
-						</text>
-					</view>
-					<view v-if="
+  <view class="ss-goods-wrap">
+    <!-- xs卡片:横向紧凑型,一行放两个,图片左内容右边  -->
+    <view
+      v-if="size === 'xs'"
+      class="xs-goods-card ss-flex ss-col-stretch"
+      :style="[elStyles]"
+      @tap="onClick"
+    >
+      <view v-if="tagStyle.show" class="tag-icon-box">
+        <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
+      </view>
+      <image class="xs-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="aspectFit" />
+      <view
+        v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show"
+        class="xs-goods-content ss-flex-col ss-row-around"
+      >
+        <view
+          v-if="goodsFields.title?.show || goodsFields.name?.show"
+          class="xs-goods-title ss-line-1"
+          :style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]"
+        >
+          {{ data.title || data.name }}
+        </view>
+        <!-- 活动信息 -->
+        <view class="iconBox" v-if="data.promotionType > 0 || data.rewardActivity">
+          <view class="card" v-if="discountText">{{ discountText }}</view>
+          <view
+            class="card2"
+            v-for="item in getRewardActivityRuleItemDescriptions(data.rewardActivity).slice(0, 1)"
+            :key="item"
+          >
+            {{ item }}
+          </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>
+          <!-- 活动价格 -->
+          <text v-if="data.promotionPrice > 0">{{ fen2yuan(data.promotionPrice) }}</text>
+          <text v-else>
+            {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
+          </text>
+        </view>
+      </view>
+    </view>
+
+    <!-- sm卡片:竖向紧凑,一行放三个,图上内容下 -->
+    <view v-if="size === 'sm'" class="sm-goods-card ss-flex-col" :style="[elStyles]" @tap="onClick">
+      <view v-if="tagStyle.show" class="tag-icon-box">
+        <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
+      </view>
+      <image
+        class="sm-img-box"
+        :src="sheep.$url.cdn(data.image || data.picUrl)"
+        mode="aspectFill"
+      ></image>
+
+      <view
+        v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show"
+        class="sm-goods-content"
+        :style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]"
+      >
+        <view
+          v-if="goodsFields.title?.show || goodsFields.name?.show"
+          class="sm-goods-title ss-line-1 ss-m-b-16"
+        >
+          {{ data.title || data.name }}
+        </view>
+        <!-- 活动信息 -->
+        <view class="iconBox" v-if="data.promotionType > 0 || data.rewardActivity">
+          <view class="card" v-if="discountText">{{ discountText }}</view>
+          <view
+            class="card2"
+            v-for="item in getRewardActivityRuleItemDescriptions(data.rewardActivity).slice(0, 1)"
+            :key="item"
+          >
+            {{ item }}
+          </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>
+          <!-- 活动价格 -->
+          <text v-if="data.promotionPrice > 0">{{ fen2yuan(data.promotionPrice) }}</text>
+          <text v-else>
+            {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
+          </text>
+        </view>
+      </view>
+    </view>
+
+    <!-- md卡片:竖向,一行放两个,图上内容下 -->
+    <view v-if="size === 'md'" class="md-goods-card ss-flex-col" :style="[elStyles]" @tap="onClick">
+      <view v-if="tagStyle.show" class="tag-icon-box">
+        <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)" />
+      </view>
+      <image class="md-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="widthFix" />
+      <view
+        class="md-goods-content ss-flex-col ss-row-around ss-p-b-20 ss-p-t-20 ss-p-x-16"
+        :id="elId"
+      >
+        <view
+          v-if="goodsFields.title?.show || goodsFields.name?.show"
+          class="md-goods-title ss-line-1"
+          :style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]"
+        >
+          {{ data.title || data.name }}
+        </view>
+        <view
+          v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
+          class="md-goods-subtitle ss-m-t-16 ss-line-1"
+          :style="[{ color: subTitleColor, background: subTitleBackground }]"
+        >
+          {{ data.subtitle || data.introduction }}
+        </view>
+        <slot name="activity">
+          <view v-if="data.promos?.length" class="tag-box ss-flex-wrap ss-flex ss-col-center">
+            <view
+              class="activity-tag ss-m-r-10 ss-m-t-16"
+              v-for="item in data.promos"
+              :key="item.id"
+            >
+              {{ item.title }}
+            </view>
+          </view>
+        </slot>
+        <!-- 活动信息 -->
+        <view class="iconBox" v-if="data.promotionType > 0 || data.rewardActivity">
+          <view class="card" v-if="discountText">{{ discountText }}</view>
+          <view
+            class="card2"
+            v-for="item in getRewardActivityRuleItemDescriptions(data.rewardActivity).slice(0, 1)"
+            :key="item"
+          >
+            {{ item }}
+          </view>
+        </view>
+        <view class="ss-flex ss-col-bottom">
+          <view
+            v-if="goodsFields.price?.show"
+            class="md-goods-price ss-m-t-16 font-OPPOSANS ss-m-r-10"
+            :style="[{ color: goodsFields.price.color }]"
+          >
+            <text class="price-unit ss-font-24">{{ priceUnit }}</text>
+            <!-- 活动价格 -->
+            <text v-if="data.promotionPrice > 0">{{ fen2yuan(data.promotionPrice) }}</text>
+            <text v-else>
+              {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
+            </text>
+          </view>
+          <view
+            v-if="
               (goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
               (goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
               (data.original_price > 0 || data.marketPrice > 0)
               (data.original_price > 0 || data.marketPrice > 0)
-            " class="goods-origin-price ss-m-t-16 font-OPPOSANS ss-flex" :style="[{ color: originPriceColor }]">
-						<text class="price-unit ss-font-20">{{ priceUnit }}</text>
-						<view class="ss-m-l-8">{{ fen2yuan(data.marketPrice) }}</view>
-					</view>
-				</view>
-
-				<view class="ss-m-t-16 ss-flex ss-col-center ss-flex-wrap">
-					<view class="sales-text">{{ salesAndStock }}</view>
-				</view>
-			</view>
-
-			<slot name="cart">
-				<view class="cart-box ss-flex ss-col-center ss-row-center">
-					<image class="cart-icon" src="/static/img/shop/tabbar/category2.png" mode="" />
-				</view>
-			</slot>
-		</view>
-
-		<!-- lg卡片:横向型,一行放一个,图片左内容右边  -->
-		<view v-if="size === 'lg'" class="lg-goods-card ss-flex ss-col-stretch" :style="[elStyles]" @tap="onClick">
-			<view v-if="tagStyle.show" class="tag-icon-box">
-				<image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
-			</view>
-			<view v-if="seckillTag" class="seckill-tag ss-flex ss-row-center">秒杀</view>
-			<view v-if="grouponTag" class="groupon-tag ss-flex ss-row-center">
-				<view class="tag-icon">拼团</view>
-			</view>
-			<image class="lg-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="aspectFill" />
-			<view class="lg-goods-content ss-flex-1 ss-flex-col ss-row-between ss-p-b-10 ss-p-t-20">
-				<view>
-					<view v-if="goodsFields.title?.show || goodsFields.name?.show" class="lg-goods-title ss-line-2"
-						:style="[{ color: titleColor }]">
-						{{ data.title || data.name }}
-					</view>
-					<view v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
-						class="lg-goods-subtitle ss-m-t-10 ss-line-1"
-						:style="[{ color: subTitleColor, background: subTitleBackground }]">
-						{{ data.subtitle || data.introduction }}
-					</view>
-				</view>
-				<view>
-					<slot name="activity">
-						<view v-if="data.promos?.length" class="tag-box ss-flex ss-col-center">
-							<view class="activity-tag ss-m-r-10" v-for="item in data.promos" :key="item.id">
-								{{ item.title }}
-							</view>
-						</view>
-					</slot>
-					<!-- 活动信息 -->
-					<view class="iconBox" v-if="data.promotionType > 0 || data.rewardActivity">
-						<view class="card" v-if="discountText">{{ discountText }}</view>
-						<view class="card2" v-if="data.rewardActivity">
-							{{ (data.rewardActivity.ruleDescriptions[0])[1] }}
-						</view>
-						<view class="card2" v-if="data.rewardActivity && (data.rewardActivity.ruleDescriptions[0])[3]">
-							{{ (data.rewardActivity.ruleDescriptions[0])[3] }}
-						</view>
-					</view>
-					<view class="ss-flex ss-col-bottom ss-m-t-10">
-						<view v-if="goodsFields.price?.show"
-							class="lg-goods-price ss-m-r-12 ss-flex ss-col-bottom font-OPPOSANS"
-							:style="[{ color: goodsFields.price.color }]">
-							<text class="ss-font-24">{{ priceUnit }}</text>
-							{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
-						</view>
-						<view v-if="
+            "
+            class="goods-origin-price ss-m-t-16 font-OPPOSANS ss-flex"
+            :style="[{ color: originPriceColor }]"
+          >
+            <text class="price-unit ss-font-20">{{ priceUnit }}</text>
+            <view class="ss-m-l-8">{{ fen2yuan(data.marketPrice) }}</view>
+          </view>
+        </view>
+
+        <view class="ss-m-t-16 ss-flex ss-col-center ss-flex-wrap">
+          <view class="sales-text">{{ salesAndStock }}</view>
+        </view>
+      </view>
+
+      <slot name="cart">
+        <view class="cart-box ss-flex ss-col-center ss-row-center">
+          <image class="cart-icon" src="/static/img/shop/tabbar/category2.png" mode="" />
+        </view>
+      </slot>
+    </view>
+
+    <!-- lg卡片:横向型,一行放一个,图片左内容右边  -->
+    <view
+      v-if="size === 'lg'"
+      class="lg-goods-card ss-flex ss-col-stretch"
+      :style="[elStyles]"
+      @tap="onClick"
+    >
+      <view v-if="tagStyle.show" class="tag-icon-box">
+        <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
+      </view>
+      <view v-if="seckillTag" class="seckill-tag ss-flex ss-row-center">秒杀</view>
+      <view v-if="grouponTag" class="groupon-tag ss-flex ss-row-center">
+        <view class="tag-icon">拼团</view>
+      </view>
+      <image
+        class="lg-img-box"
+        :src="sheep.$url.cdn(data.image || data.picUrl)"
+        mode="aspectFill"
+      />
+      <view class="lg-goods-content ss-flex-1 ss-flex-col ss-row-between ss-p-b-10 ss-p-t-20">
+        <view>
+          <view
+            v-if="goodsFields.title?.show || goodsFields.name?.show"
+            class="lg-goods-title ss-line-2"
+            :style="[{ color: titleColor }]"
+          >
+            {{ data.title || data.name }}
+          </view>
+          <view
+            v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
+            class="lg-goods-subtitle ss-m-t-10 ss-line-1"
+            :style="[{ color: subTitleColor, background: subTitleBackground }]"
+          >
+            {{ data.subtitle || data.introduction }}
+          </view>
+        </view>
+        <view>
+          <slot name="activity">
+            <view v-if="data.promos?.length" class="tag-box ss-flex ss-col-center">
+              <view class="activity-tag ss-m-r-10" v-for="item in data.promos" :key="item.id">
+                {{ item.title }}
+              </view>
+            </view>
+          </slot>
+          <!-- 活动信息 -->
+          <view class="iconBox" v-if="data.promotionType > 0 || data.rewardActivity">
+            <view class="card" v-if="discountText">{{ discountText }}</view>
+            <view
+              class="card2"
+              v-for="item in getRewardActivityRuleItemDescriptions(data.rewardActivity).slice(0, 1)"
+              :key="item"
+            >
+              {{ item }}
+            </view>
+          </view>
+          <view class="ss-flex ss-col-bottom ss-m-t-10">
+            <view
+              v-if="goodsFields.price?.show"
+              class="lg-goods-price ss-m-r-12 ss-flex ss-col-bottom font-OPPOSANS"
+              :style="[{ color: goodsFields.price.color }]"
+            >
+              <text class="ss-font-24">{{ priceUnit }}</text>
+              {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
+            </view>
+            <view
+              v-if="
                 (goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
                 (goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
                 (data.original_price > 0 || data.marketPrice > 0)
                 (data.original_price > 0 || data.marketPrice > 0)
-              " class="goods-origin-price ss-flex ss-col-bottom font-OPPOSANS" :style="[{ color: originPriceColor }]">
-							<text class="price-unit ss-font-20">{{ priceUnit }}</text>
-							<!-- 活动价格 -->
-							<text v-if="data.promotionPrice > 0">{{ fen2yuan(data.promotionPrice) }}</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">
-						<view class="sales-text">{{ salesAndStock }}</view>
-					</view>
-				</view>
-			</view>
-
-			<slot name="cart">
-				<view class="buy-box ss-flex ss-col-center ss-row-center" v-if="buttonShow"> 去购买 </view>
-			</slot>
-		</view>
-
-		<!-- sl卡片:竖向型,一行放一个,图片上内容下边 -->
-		<view v-if="size === 'sl'" class="sl-goods-card ss-flex-col" :style="[elStyles]" @tap="onClick">
-			<view v-if="tagStyle.show" class="tag-icon-box">
-				<image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)" />
-			</view>
-			<image class="sl-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="aspectFill" />
-			<view class="sl-goods-content">
-				<view>
-					<view v-if="goodsFields.title?.show || goodsFields.name?.show" class="sl-goods-title ss-line-1"
-						:style="[{ color: titleColor }]">
-						{{ data.title || data.name }}
-					</view>
-					<view v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
-						class="sl-goods-subtitle ss-m-t-16"
-						:style="[{ color: subTitleColor, background: subTitleBackground }]">
-						{{ data.subtitle || data.introduction }}
-					</view>
-				</view>
-				<view>
-					<slot name="activity">
-						<view v-if="data.promos?.length" class="tag-box ss-flex ss-col-center ss-flex-wrap">
-							<view class="activity-tag ss-m-r-10 ss-m-t-16" v-for="item in data.promos" :key="item.id">
-								{{ item.title }}
-							</view>
-						</view>
-					</slot>
-					<!-- 活动信息 -->
-					<view class="iconBox" v-if="data.promotionType > 0 || data.rewardActivity">
-						<view class="card" v-if="discountText">{{ discountText }}</view>
-						<view class="card2" v-if="data.rewardActivity">
-							{{ (data.rewardActivity.ruleDescriptions[0])[1] }}
-						</view>
-						<view class="card2" v-if="data.rewardActivity && (data.rewardActivity.ruleDescriptions[0])[3]">
-							{{ (data.rewardActivity.ruleDescriptions[0])[3] }}
-						</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>
-							<!-- 活动价格 -->
-							<text v-if="data.promotionPrice > 0">{{ fen2yuan(data.promotionPrice) }}</text>
-							<text v-else>
-								{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
-							</text>
-						</view>
-						<view v-if="
+              "
+              class="goods-origin-price ss-flex ss-col-bottom font-OPPOSANS"
+              :style="[{ color: originPriceColor }]"
+            >
+              <text class="price-unit ss-font-20">{{ priceUnit }}</text>
+              <!-- 活动价格 -->
+              <text v-if="data.promotionPrice > 0">{{ fen2yuan(data.promotionPrice) }}</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">
+            <view class="sales-text">{{ salesAndStock }}</view>
+          </view>
+        </view>
+      </view>
+
+      <slot name="cart">
+        <view class="buy-box ss-flex ss-col-center ss-row-center" v-if="buttonShow"> 去购买 </view>
+      </slot>
+    </view>
+
+    <!-- sl卡片:竖向型,一行放一个,图片上内容下边 -->
+    <view v-if="size === 'sl'" class="sl-goods-card ss-flex-col" :style="[elStyles]" @tap="onClick">
+      <view v-if="tagStyle.show" class="tag-icon-box">
+        <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)" />
+      </view>
+      <image
+        class="sl-img-box"
+        :src="sheep.$url.cdn(data.image || data.picUrl)"
+        mode="aspectFill"
+      />
+      <view class="sl-goods-content">
+        <view>
+          <view
+            v-if="goodsFields.title?.show || goodsFields.name?.show"
+            class="sl-goods-title ss-line-1"
+            :style="[{ color: titleColor }]"
+          >
+            {{ data.title || data.name }}
+          </view>
+          <view
+            v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
+            class="sl-goods-subtitle ss-m-t-16"
+            :style="[{ color: subTitleColor, background: subTitleBackground }]"
+          >
+            {{ data.subtitle || data.introduction }}
+          </view>
+        </view>
+        <view>
+          <slot name="activity">
+            <view v-if="data.promos?.length" class="tag-box ss-flex ss-col-center ss-flex-wrap">
+              <view
+                class="activity-tag ss-m-r-10 ss-m-t-16"
+                v-for="item in data.promos"
+                :key="item.id"
+              >
+                {{ item.title }}
+              </view>
+            </view>
+          </slot>
+          <!-- 活动信息 -->
+          <view class="iconBox" v-if="data.promotionType > 0 || data.rewardActivity">
+            <view class="card" v-if="discountText">{{ discountText }}</view>
+            <view
+              class="card2"
+              v-for="item in getRewardActivityRuleItemDescriptions(data.rewardActivity).slice(0, 1)"
+              :key="item"
+            >
+              {{ item }}
+            </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>
+              <!-- 活动价格 -->
+              <text v-if="data.promotionPrice > 0">{{ fen2yuan(data.promotionPrice) }}</text>
+              <text v-else>
+                {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
+              </text>
+            </view>
+            <view
+              v-if="
                 (goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
                 (goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
                 (data.original_price > 0 || data.marketPrice > 0)
                 (data.original_price > 0 || data.marketPrice > 0)
-              " class="goods-origin-price ss-m-t-16 font-OPPOSANS ss-flex" :style="[{ color: originPriceColor }]">
-							<text class="price-unit ss-font-20">{{ priceUnit }}</text>
-							<view class="ss-m-l-8">{{ fen2yuan(data.marketPrice) }}</view>
-						</view>
-					</view>
-					<view class="ss-m-t-16 ss-flex ss-flex-wrap">
-						<view class="sales-text">{{ salesAndStock }}</view>
-					</view>
-				</view>
-			</view>
-
-			<slot name="cart">
-				<view class="buy-box ss-flex ss-col-center ss-row-center">去购买</view>
-			</slot>
-		</view>
-	</view>
+              "
+              class="goods-origin-price ss-m-t-16 font-OPPOSANS ss-flex"
+              :style="[{ color: originPriceColor }]"
+            >
+              <text class="price-unit ss-font-20">{{ priceUnit }}</text>
+              <view class="ss-m-l-8">{{ fen2yuan(data.marketPrice) }}</view>
+            </view>
+          </view>
+          <view class="ss-m-t-16 ss-flex ss-flex-wrap">
+            <view class="sales-text">{{ salesAndStock }}</view>
+          </view>
+        </view>
+      </view>
+
+      <slot name="cart">
+        <view class="buy-box ss-flex ss-col-center ss-row-center">去购买</view>
+      </slot>
+    </view>
+  </view>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-	/**
-	 * 商品卡片
-	 *
-	 * @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 {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									- 销售数量颜色
-	 *
-	 * @slots activity												 	- 活动插槽
-	 * @slots cart														- 购物车插槽,默认包含文字,背景色,文字颜色 || 图片 || 行为
-	 *
-	 * @event {Function()} click 										- 点击卡片
-	 *
-	 */
-	import {
-		computed,
-		getCurrentInstance,
-		onMounted,
-		nextTick
-	} from 'vue';
-	import sheep from '@/sheep';
-	import {
-		fen2yuan,
-		formatSales
-	} from '@/sheep/hooks/useGoods';
-	import {
-		formatStock
-	} from '@/sheep/hooks/useGoods';
-	import {
-		isArray
-	} from 'lodash-es';
-
-	// 接收参数
-	const props = defineProps({
-		goodsFields: {
-			type: [Array, Object],
-			default () {
-				return {
-					// 商品价格
-					price: {
-						show: true,
-					},
-					// 库存
-					stock: {
-						show: true,
-					},
-					// 商品名称
-					name: {
-						show: true,
-					},
-					// 商品介绍
-					introduction: {
-						show: true,
-					},
-					// 市场价
-					marketPrice: {
-						show: true,
-					},
-					// 销量
-					salesCount: {
-						show: true,
-					},
-				};
-			},
-		},
-		tagStyle: {
-			type: Object,
-			default: () => ({}),
-		},
-		data: {
-			type: Object,
-			default: () => ({}),
-		},
-		size: {
-			type: String,
-			default: 'sl',
-		},
-		background: {
-			type: String,
-			default: '',
-		},
-		topRadius: {
-			type: Number,
-			default: 0,
-		},
-		bottomRadius: {
-			type: Number,
-			default: 0,
-		},
-		titleWidth: {
-			type: Number,
-			default: 0,
-		},
-		titleColor: {
-			type: String,
-			default: '#333',
-		},
-		priceColor: {
-			type: String,
-			default: '',
-		},
-		originPriceColor: {
-			type: String,
-			default: '#C4C4C4',
-		},
-		priceUnit: {
-			type: String,
-			default: '¥',
-		},
-		subTitleColor: {
-			type: String,
-			default: '#999999',
-		},
-		subTitleBackground: {
-			type: String,
-			default: '',
-		},
-		buttonShow: {
-			type: Boolean,
-			default: true,
-		},
-		seckillTag: {
-			type: Boolean,
-			default: false,
-		},
-		grouponTag: {
-			type: Boolean,
-			default: false,
-		},
-	});
-
-	// 优惠文案
-	const discountText = computed(() => {
-		const promotionType = props.data.promotionType;
-		if (promotionType === 4) {
-			return '限时优惠';
-		} else if (promotionType === 6) {
-			return '会员价';
-		}
-		return undefined;
-	});
-
-	// 组件样式
-	const elStyles = computed(() => {
-		return {
-			background: props.background,
-			'border-top-left-radius': props.topRadius + 'px',
-			'border-top-right-radius': props.topRadius + 'px',
-			'border-bottom-left-radius': props.bottomRadius + 'px',
-			'border-bottom-right-radius': props.bottomRadius + 'px',
-		};
-	});
-
-	// 格式化销量、库存信息
-	const salesAndStock = computed(() => {
-		let text = [];
-		if (props.goodsFields.salesCount?.show) {
-			text.push(formatSales(props.data.sales_show_type, props.data.salesCount));
-		}
-		if (props.goodsFields.stock?.show) {
-			text.push(formatStock(props.data.stock_show_type, props.data.stock));
-		}
-		return text.join(' | ');
-	});
-
-	// 返回事件
-	const emits = defineEmits(['click', 'getHeight']);
-
-	const onClick = () => {
-		emits('click');
-	};
-
-	// 获取卡片实时高度
-	const {
-		proxy
-	} = getCurrentInstance();
-	const elId = `sheep_${Math.ceil(Math.random() * 10e5).toString(36)}`;
-
-	function getGoodsPriceCardWH() {
-		if (props.size === 'md') {
-			const view = uni.createSelectorQuery().in(proxy);
-			view.select(`#${elId}`).fields({
-				size: true,
-				scrollOffset: true,
-			});
-			view.exec((data) => {
-				let totalHeight = 0;
-				const goodsPriceCard = data[0];
-				if (props.data.image_wh) {
-					totalHeight =
-						(goodsPriceCard.width / props.data.image_wh.w) * props.data.image_wh.h +
-						goodsPriceCard.height;
-				} else {
-					totalHeight = goodsPriceCard.width;
-				}
-				emits('getHeight', totalHeight);
-			});
-		}
-	}
-	onMounted(() => {
-		nextTick(() => {
-			getGoodsPriceCardWH();
-		});
-	});
+  /**
+   * 商品卡片
+   *
+   * @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 {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									- 销售数量颜色
+   *
+   * @slots activity												 	- 活动插槽
+   * @slots cart														- 购物车插槽,默认包含文字,背景色,文字颜色 || 图片 || 行为
+   *
+   * @event {Function()} click 										- 点击卡片
+   *
+   */
+  import { computed, getCurrentInstance, onMounted, nextTick } from 'vue';
+  import sheep from '@/sheep';
+  import {
+    fen2yuan,
+    formatSales,
+    getRewardActivityRuleItemDescriptions,
+  } from '@/sheep/hooks/useGoods';
+  import { formatStock } from '@/sheep/hooks/useGoods';
+  import { isArray } from 'lodash-es';
+
+  // 接收参数
+  const props = defineProps({
+    goodsFields: {
+      type: [Array, Object],
+      default() {
+        return {
+          // 商品价格
+          price: {
+            show: true,
+          },
+          // 库存
+          stock: {
+            show: true,
+          },
+          // 商品名称
+          name: {
+            show: true,
+          },
+          // 商品介绍
+          introduction: {
+            show: true,
+          },
+          // 市场价
+          marketPrice: {
+            show: true,
+          },
+          // 销量
+          salesCount: {
+            show: true,
+          },
+        };
+      },
+    },
+    tagStyle: {
+      type: Object,
+      default: () => ({}),
+    },
+    data: {
+      type: Object,
+      default: () => ({}),
+    },
+    size: {
+      type: String,
+      default: 'sl',
+    },
+    background: {
+      type: String,
+      default: '',
+    },
+    topRadius: {
+      type: Number,
+      default: 0,
+    },
+    bottomRadius: {
+      type: Number,
+      default: 0,
+    },
+    titleWidth: {
+      type: Number,
+      default: 0,
+    },
+    titleColor: {
+      type: String,
+      default: '#333',
+    },
+    priceColor: {
+      type: String,
+      default: '',
+    },
+    originPriceColor: {
+      type: String,
+      default: '#C4C4C4',
+    },
+    priceUnit: {
+      type: String,
+      default: '¥',
+    },
+    subTitleColor: {
+      type: String,
+      default: '#999999',
+    },
+    subTitleBackground: {
+      type: String,
+      default: '',
+    },
+    buttonShow: {
+      type: Boolean,
+      default: true,
+    },
+    seckillTag: {
+      type: Boolean,
+      default: false,
+    },
+    grouponTag: {
+      type: Boolean,
+      default: false,
+    },
+  });
+
+  // 优惠文案
+  const discountText = computed(() => {
+    const promotionType = props.data.promotionType;
+    if (promotionType === 4) {
+      return '限时优惠';
+    } else if (promotionType === 6) {
+      return '会员价';
+    }
+    return undefined;
+  });
+
+  // 组件样式
+  const elStyles = computed(() => {
+    return {
+      background: props.background,
+      'border-top-left-radius': props.topRadius + 'px',
+      'border-top-right-radius': props.topRadius + 'px',
+      'border-bottom-left-radius': props.bottomRadius + 'px',
+      'border-bottom-right-radius': props.bottomRadius + 'px',
+    };
+  });
+
+  // 格式化销量、库存信息
+  const salesAndStock = computed(() => {
+    let text = [];
+    if (props.goodsFields.salesCount?.show) {
+      text.push(formatSales(props.data.sales_show_type, props.data.salesCount));
+    }
+    if (props.goodsFields.stock?.show) {
+      text.push(formatStock(props.data.stock_show_type, props.data.stock));
+    }
+    return text.join(' | ');
+  });
+
+  // 返回事件
+  const emits = defineEmits(['click', 'getHeight']);
+
+  const onClick = () => {
+    emits('click');
+  };
+
+  // 获取卡片实时高度
+  const { proxy } = getCurrentInstance();
+  const elId = `sheep_${Math.ceil(Math.random() * 10e5).toString(36)}`;
+
+  function getGoodsPriceCardWH() {
+    if (props.size === 'md') {
+      const view = uni.createSelectorQuery().in(proxy);
+      view.select(`#${elId}`).fields({
+        size: true,
+        scrollOffset: true,
+      });
+      view.exec((data) => {
+        let totalHeight = 0;
+        const goodsPriceCard = data[0];
+        if (props.data.image_wh) {
+          totalHeight =
+            (goodsPriceCard.width / props.data.image_wh.w) * props.data.image_wh.h +
+            goodsPriceCard.height;
+        } else {
+          totalHeight = goodsPriceCard.width;
+        }
+        emits('getHeight', totalHeight);
+      });
+    }
+  }
+  onMounted(() => {
+    nextTick(() => {
+      getGoodsPriceCardWH();
+    });
+  });
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-	.tag-icon-box {
-		position: absolute;
-		left: 0;
-		top: 0;
-		z-index: 2;
-
-		.tag-icon {
-			width: 72rpx;
-			height: 44rpx;
-		}
-	}
-
-	.seckill-tag {
-		position: absolute;
-		left: 0;
-		top: 0;
-		z-index: 2;
-		width: 68rpx;
-		height: 38rpx;
-		background: linear-gradient(90deg, #ff5854 0%, #ff2621 100%);
-		border-radius: 10rpx 0px 10rpx 0px;
-		font-size: 24rpx;
-		font-weight: 500;
-		color: #ffffff;
-		line-height: 32rpx;
-	}
-
-	.groupon-tag {
-		position: absolute;
-		left: 0;
-		top: 0;
-		z-index: 2;
-		width: 68rpx;
-		height: 38rpx;
-		background: linear-gradient(90deg, #fe832a 0%, #ff6600 100%);
-		border-radius: 10rpx 0px 10rpx 0px;
-		font-size: 24rpx;
-		font-weight: 500;
-		color: #ffffff;
-		line-height: 32rpx;
-	}
-
-	.goods-img {
-		width: 100%;
-		height: 100%;
-		background-color: #f5f5f5;
-	}
-
-	.price-unit {
-		margin-right: -4px;
-	}
-
-	.sales-text {
-		display: table;
-		font-size: 24rpx;
-		transform: scale(0.8);
-		margin-left: 0rpx;
-		color: #c4c4c4;
-	}
-
-	.activity-tag {
-		font-size: 20rpx;
-		color: #ff0000;
-		line-height: 30rpx;
-		padding: 0 10rpx;
-		border: 1px solid rgba(#ff0000, 0.25);
-		border-radius: 4px;
-		flex-shrink: 0;
-	}
-
-	.goods-origin-price {
-		font-size: 20rpx;
-		color: #c4c4c4;
-		line-height: 36rpx;
-		text-decoration: line-through;
-	}
-
-	// xs
-	.xs-goods-card {
-		overflow: hidden;
-		// max-width: 375rpx;
-		background-color: $white;
-		position: relative;
-
-		.xs-img-box {
-			width: 128rpx;
-			height: 128rpx;
-			margin-right: 20rpx;
-		}
-
-		.xs-goods-title {
-			font-size: 26rpx;
-			color: #333;
-			font-weight: 500;
-		}
-
-		.xs-goods-price {
-			font-size: 30rpx;
-			color: $red;
-		}
-	}
-
-	// sm
-	.sm-goods-card {
-		overflow: hidden;
-		// width: 223rpx;
-		// width: 100%;
-		background-color: $white;
-		position: relative;
-
-		.sm-img-box {
-			// width: 228rpx;
-			width: 100%;
-			height: 208rpx;
-		}
-
-		.sm-goods-content {
-			padding: 20rpx 16rpx;
-			box-sizing: border-box;
-		}
-
-		.sm-goods-title {
-			font-size: 26rpx;
-			color: #333;
-		}
-
-		.sm-goods-price {
-			font-size: 30rpx;
-			color: $red;
-		}
-	}
-
-	// md
-	.md-goods-card {
-		overflow: hidden;
-		width: 100%;
-		position: relative;
-		z-index: 1;
-		background-color: $white;
-		position: relative;
-
-		.md-img-box {
-			width: 100%;
-		}
-
-		.md-goods-title {
-			font-size: 26rpx;
-			color: #333;
-			width: 100%;
-		}
-
-		.md-goods-subtitle {
-			font-size: 24rpx;
-			font-weight: 400;
-			color: #999999;
-		}
-
-		.md-goods-price {
-			font-size: 30rpx;
-			color: $red;
-			line-height: 36rpx;
-		}
-
-		.cart-box {
-			width: 54rpx;
-			height: 54rpx;
-			background: linear-gradient(90deg, #fe8900, #ff5e00);
-			border-radius: 50%;
-			position: absolute;
-			bottom: 50rpx;
-			right: 20rpx;
-			z-index: 2;
-
-			.cart-icon {
-				width: 30rpx;
-				height: 30rpx;
-			}
-		}
-	}
-
-	// lg
-	.lg-goods-card {
-		overflow: hidden;
-		position: relative;
-		z-index: 1;
-		background-color: $white;
-		height: 280rpx;
-
-		.lg-img-box {
-			width: 280rpx;
-			height: 280rpx;
-			margin-right: 20rpx;
-		}
-
-		.lg-goods-title {
-			font-size: 28rpx;
-			font-weight: 500;
-			color: #333333;
-			// line-height: 36rpx;
-			// width: 410rpx;
-		}
-
-		.lg-goods-subtitle {
-			font-size: 24rpx;
-			font-weight: 400;
-			color: #999999;
-			// line-height: 30rpx;
-			// width: 410rpx;
-		}
-
-		.lg-goods-price {
-			font-size: 30rpx;
-			color: $red;
-			line-height: 36rpx;
-		}
-
-		.buy-box {
-			position: absolute;
-			bottom: 20rpx;
-			right: 20rpx;
-			z-index: 2;
-			width: 120rpx;
-			height: 50rpx;
-			background: linear-gradient(90deg, #fe8900, #ff5e00);
-			border-radius: 25rpx;
-			font-size: 24rpx;
-			color: #ffffff;
-		}
-
-		.tag-box {
-			width: 100%;
-		}
-	}
-
-	// sl
-
-	.sl-goods-card {
-		overflow: hidden;
-		position: relative;
-		z-index: 1;
-		width: 100%;
-		background-color: $white;
-
-		.sl-goods-content {
-			padding: 20rpx 20rpx;
-			box-sizing: border-box;
-		}
-
-		.sl-img-box {
-			width: 100%;
-			height: 360rpx;
-		}
-
-		.sl-goods-title {
-			font-size: 26rpx;
-			color: #333;
-			font-weight: 500;
-		}
-
-		.sl-goods-subtitle {
-			font-size: 24rpx;
-			font-weight: 400;
-			color: #999999;
-			line-height: 30rpx;
-		}
-
-		.sl-goods-price {
-			font-size: 30rpx;
-			color: $red;
-			line-height: 36rpx;
-		}
-
-		.buy-box {
-			position: absolute;
-			bottom: 20rpx;
-			right: 20rpx;
-			z-index: 2;
-			width: 148rpx;
-			height: 50rpx;
-			background: linear-gradient(90deg, #fe8900, #ff5e00);
-			border-radius: 25rpx;
-			font-size: 24rpx;
-			color: #ffffff;
-		}
-	}
-
-	.card {
-		width: fit-content;
-		height: fit-content;
-		padding: 2rpx 10rpx;
-		background-color: red;
-		color: #ffffff;
-		font-size: 24rpx;
-		margin-top: 5rpx;
-	}
-
-	.card2 {
-		width: fit-content;
-		height: fit-content;
-		padding: 2rpx 10rpx;
-		background-color: rgb(255, 242, 241);
-		color: #ff2621;
-		font-size: 24rpx;
-		margin: 5rpx 0 5rpx 5rpx;
-	}
-
-	.iconBox {
-		width: 100%;
-		height: fit-content;
-		margin-top: 10rpx;
-		display: flex;
-		justify-content: flex-start;
-		flex-wrap: wrap;
-	}
-</style>
+  .tag-icon-box {
+    position: absolute;
+    left: 0;
+    top: 0;
+    z-index: 2;
+
+    .tag-icon {
+      width: 72rpx;
+      height: 44rpx;
+    }
+  }
+
+  .seckill-tag {
+    position: absolute;
+    left: 0;
+    top: 0;
+    z-index: 2;
+    width: 68rpx;
+    height: 38rpx;
+    background: linear-gradient(90deg, #ff5854 0%, #ff2621 100%);
+    border-radius: 10rpx 0px 10rpx 0px;
+    font-size: 24rpx;
+    font-weight: 500;
+    color: #ffffff;
+    line-height: 32rpx;
+  }
+
+  .groupon-tag {
+    position: absolute;
+    left: 0;
+    top: 0;
+    z-index: 2;
+    width: 68rpx;
+    height: 38rpx;
+    background: linear-gradient(90deg, #fe832a 0%, #ff6600 100%);
+    border-radius: 10rpx 0px 10rpx 0px;
+    font-size: 24rpx;
+    font-weight: 500;
+    color: #ffffff;
+    line-height: 32rpx;
+  }
+
+  .goods-img {
+    width: 100%;
+    height: 100%;
+    background-color: #f5f5f5;
+  }
+
+  .price-unit {
+    margin-right: -4px;
+  }
+
+  .sales-text {
+    display: table;
+    font-size: 24rpx;
+    transform: scale(0.8);
+    margin-left: 0rpx;
+    color: #c4c4c4;
+  }
+
+  .activity-tag {
+    font-size: 20rpx;
+    color: #ff0000;
+    line-height: 30rpx;
+    padding: 0 10rpx;
+    border: 1px solid rgba(#ff0000, 0.25);
+    border-radius: 4px;
+    flex-shrink: 0;
+  }
+
+  .goods-origin-price {
+    font-size: 20rpx;
+    color: #c4c4c4;
+    line-height: 36rpx;
+    text-decoration: line-through;
+  }
+
+  // xs
+  .xs-goods-card {
+    overflow: hidden;
+    // max-width: 375rpx;
+    background-color: $white;
+    position: relative;
+
+    .xs-img-box {
+      width: 128rpx;
+      height: 128rpx;
+      margin-right: 20rpx;
+    }
+
+    .xs-goods-title {
+      font-size: 26rpx;
+      color: #333;
+      font-weight: 500;
+    }
+
+    .xs-goods-price {
+      font-size: 30rpx;
+      color: $red;
+    }
+  }
+
+  // sm
+  .sm-goods-card {
+    overflow: hidden;
+    // width: 223rpx;
+    // width: 100%;
+    background-color: $white;
+    position: relative;
+
+    .sm-img-box {
+      // width: 228rpx;
+      width: 100%;
+      height: 208rpx;
+    }
+
+    .sm-goods-content {
+      padding: 20rpx 16rpx;
+      box-sizing: border-box;
+    }
+
+    .sm-goods-title {
+      font-size: 26rpx;
+      color: #333;
+    }
+
+    .sm-goods-price {
+      font-size: 30rpx;
+      color: $red;
+    }
+  }
+
+  // md
+  .md-goods-card {
+    overflow: hidden;
+    width: 100%;
+    position: relative;
+    z-index: 1;
+    background-color: $white;
+    position: relative;
+
+    .md-img-box {
+      width: 100%;
+    }
+
+    .md-goods-title {
+      font-size: 26rpx;
+      color: #333;
+      width: 100%;
+    }
+
+    .md-goods-subtitle {
+      font-size: 24rpx;
+      font-weight: 400;
+      color: #999999;
+    }
+
+    .md-goods-price {
+      font-size: 30rpx;
+      color: $red;
+      line-height: 36rpx;
+    }
+
+    .cart-box {
+      width: 54rpx;
+      height: 54rpx;
+      background: linear-gradient(90deg, #fe8900, #ff5e00);
+      border-radius: 50%;
+      position: absolute;
+      bottom: 50rpx;
+      right: 20rpx;
+      z-index: 2;
+
+      .cart-icon {
+        width: 30rpx;
+        height: 30rpx;
+      }
+    }
+  }
+
+  // lg
+  .lg-goods-card {
+    overflow: hidden;
+    position: relative;
+    z-index: 1;
+    background-color: $white;
+    height: 280rpx;
+
+    .lg-img-box {
+      width: 280rpx;
+      height: 280rpx;
+      margin-right: 20rpx;
+    }
+
+    .lg-goods-title {
+      font-size: 28rpx;
+      font-weight: 500;
+      color: #333333;
+      // line-height: 36rpx;
+      // width: 410rpx;
+    }
+
+    .lg-goods-subtitle {
+      font-size: 24rpx;
+      font-weight: 400;
+      color: #999999;
+      // line-height: 30rpx;
+      // width: 410rpx;
+    }
+
+    .lg-goods-price {
+      font-size: 30rpx;
+      color: $red;
+      line-height: 36rpx;
+    }
+
+    .buy-box {
+      position: absolute;
+      bottom: 20rpx;
+      right: 20rpx;
+      z-index: 2;
+      width: 120rpx;
+      height: 50rpx;
+      background: linear-gradient(90deg, #fe8900, #ff5e00);
+      border-radius: 25rpx;
+      font-size: 24rpx;
+      color: #ffffff;
+    }
+
+    .tag-box {
+      width: 100%;
+    }
+  }
+
+  // sl
+
+  .sl-goods-card {
+    overflow: hidden;
+    position: relative;
+    z-index: 1;
+    width: 100%;
+    background-color: $white;
+
+    .sl-goods-content {
+      padding: 20rpx 20rpx;
+      box-sizing: border-box;
+    }
+
+    .sl-img-box {
+      width: 100%;
+      height: 360rpx;
+    }
+
+    .sl-goods-title {
+      font-size: 26rpx;
+      color: #333;
+      font-weight: 500;
+    }
+
+    .sl-goods-subtitle {
+      font-size: 24rpx;
+      font-weight: 400;
+      color: #999999;
+      line-height: 30rpx;
+    }
+
+    .sl-goods-price {
+      font-size: 30rpx;
+      color: $red;
+      line-height: 36rpx;
+    }
+
+    .buy-box {
+      position: absolute;
+      bottom: 20rpx;
+      right: 20rpx;
+      z-index: 2;
+      width: 148rpx;
+      height: 50rpx;
+      background: linear-gradient(90deg, #fe8900, #ff5e00);
+      border-radius: 25rpx;
+      font-size: 24rpx;
+      color: #ffffff;
+    }
+  }
+
+  .card {
+    width: fit-content;
+    height: fit-content;
+    padding: 2rpx 10rpx;
+    background-color: red;
+    color: #ffffff;
+    font-size: 24rpx;
+    margin-top: 5rpx;
+  }
+
+  .card2 {
+    width: fit-content;
+    height: fit-content;
+    padding: 2rpx 10rpx;
+    background-color: rgb(255, 242, 241);
+    color: #ff2621;
+    font-size: 24rpx;
+    margin: 5rpx 0 5rpx 5rpx;
+  }
+
+  .iconBox {
+    width: 100%;
+    height: fit-content;
+    margin-top: 10rpx;
+    display: flex;
+    justify-content: flex-start;
+    flex-wrap: wrap;
+  }
+</style>

+ 338 - 288
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';
 
 
 /**
 /**
  * 格式化销量
  * 格式化销量
@@ -14,8 +10,8 @@ import {
  * @return {string} 格式化后的销量字符串
  * @return {string} 格式化后的销量字符串
  */
  */
 export function formatSales(type, num) {
 export function formatSales(type, num) {
-	let prefix = type !== 'exact' && num < 10 ? '销量' : '已售';
-	return formatNum(prefix, type, num);
+  let prefix = type !== 'exact' && num < 10 ? '销量' : '已售';
+  return formatNum(prefix, type, num);
 }
 }
 
 
 /**
 /**
@@ -25,7 +21,7 @@ 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);
 }
 }
 
 
 /**
 /**
@@ -35,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);
 }
 }
 
 
 /**
 /**
@@ -46,27 +42,27 @@ export function formatStock(type, num) {
  * @return {string} 格式化后的销量字符串
  * @return {string} 格式化后的销量字符串
  */
  */
 export function formatNum(prefix, type, num) {
 export function formatNum(prefix, type, num) {
-	num = num || 0;
-	// 情况一:精确数值
-	if (type === 'exact') {
-		return prefix + num;
-	}
-	// 情况二:小于等于 10
-	if (num < 10) {
-		return `${prefix}≤10`;
-	}
-	// 情况三:大于 10,除第一位外,其它位都显示为0
-	// 例如:100  - 199  显示为 100+
-	//      9000 - 9999 显示为 9000+
-	const numStr = num.toString();
-	const first = numStr[0];
-	const other = '0'.repeat(numStr.length - 1);
-	return `${prefix}${first}${other}+`;
+  num = num || 0;
+  // 情况一:精确数值
+  if (type === 'exact') {
+    return prefix + num;
+  }
+  // 情况二:小于等于 10
+  if (num < 10) {
+    return `${prefix}≤10`;
+  }
+  // 情况三:大于 10,除第一位外,其它位都显示为0
+  // 例如:100  - 199  显示为 100+
+  //      9000 - 9999 显示为 9000+
+  const numStr = num.toString();
+  const first = numStr[0];
+  const other = '0'.repeat(numStr.length - 1);
+  return `${prefix}${first}${other}+`;
 }
 }
 
 
 // 格式化价格
 // 格式化价格
 export function formatPrice(e) {
 export function formatPrice(e) {
-	return e.length === 1 ? e[0] : e.join('~');
+  return e.length === 1 ? e[0] : e.join('~');
 }
 }
 
 
 // 视频格式后缀列表
 // 视频格式后缀列表
@@ -79,19 +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,16 +97,16 @@ export function formatGoodsSwiper(urlList) {
  * @return {string} 颜色的 class 名称
  * @return {string} 颜色的 class 名称
  */
  */
 export function formatOrderColor(order) {
 export function formatOrderColor(order) {
-	if (order.status === 0) {
-		return 'info-color';
-	}
-	if (order.status === 10 || order.status === 20 || (order.status === 30 && !order.commentStatus)) {
-		return 'warning-color';
-	}
-	if (order.status === 30 && order.commentStatus) {
-		return 'success-color';
-	}
-	return 'danger-color';
+  if (order.status === 0) {
+    return 'info-color';
+  }
+  if (order.status === 10 || order.status === 20 || (order.status === 30 && !order.commentStatus)) {
+    return 'warning-color';
+  }
+  if (order.status === 30 && order.commentStatus) {
+    return 'success-color';
+  }
+  return 'danger-color';
 }
 }
 
 
 /**
 /**
@@ -119,25 +115,25 @@ export function formatOrderColor(order) {
  * @param order 订单
  * @param order 订单
  */
  */
 export function formatOrderStatus(order) {
 export function formatOrderStatus(order) {
-	if (order.status === 0) {
-		return '待付款';
-	}
-	if (order.status === 10 && order.deliveryType === 1) {
-		return '待发货';
-	}
-	if (order.status === 10 && order.deliveryType === 2) {
-		return '待核销';
-	}
-	if (order.status === 20) {
-		return '待收货';
-	}
-	if (order.status === 30 && !order.commentStatus) {
-		return '待评价';
-	}
-	if (order.status === 30 && order.commentStatus) {
-		return '已完成';
-	}
-	return '已关闭';
+  if (order.status === 0) {
+    return '待付款';
+  }
+  if (order.status === 10 && order.deliveryType === 1) {
+    return '待发货';
+  }
+  if (order.status === 10 && order.deliveryType === 2) {
+    return '待核销';
+  }
+  if (order.status === 20) {
+    return '待收货';
+  }
+  if (order.status === 30 && !order.commentStatus) {
+    return '待评价';
+  }
+  if (order.status === 30 && order.commentStatus) {
+    return '已完成';
+  }
+  return '已关闭';
 }
 }
 
 
 /**
 /**
@@ -146,22 +142,22 @@ export function formatOrderStatus(order) {
  * @param order 订单
  * @param order 订单
  */
  */
 export function formatOrderStatusDescription(order) {
 export function formatOrderStatusDescription(order) {
-	if (order.status === 0) {
-		return `请在 ${formatDate(order.payExpireTime)} 前完成支付`;
-	}
-	if (order.status === 10) {
-		return '商家未发货,请耐心等待';
-	}
-	if (order.status === 20) {
-		return '商家已发货,请耐心等待';
-	}
-	if (order.status === 30 && !order.commentStatus) {
-		return '已收货,快去评价一下吧';
-	}
-	if (order.status === 30 && order.commentStatus) {
-		return '交易完成,感谢您的支持';
-	}
-	return '交易关闭';
+  if (order.status === 0) {
+    return `请在 ${formatDate(order.payExpireTime)} 前完成支付`;
+  }
+  if (order.status === 10) {
+    return '商家未发货,请耐心等待';
+  }
+  if (order.status === 20) {
+    return '商家已发货,请耐心等待';
+  }
+  if (order.status === 30 && !order.commentStatus) {
+    return '已收货,快去评价一下吧';
+  }
+  if (order.status === 30 && order.commentStatus) {
+    return '交易完成,感谢您的支持';
+  }
+  return '交易关闭';
 }
 }
 
 
 /**
 /**
@@ -170,32 +166,32 @@ export function formatOrderStatusDescription(order) {
  * @param order 订单
  * @param order 订单
  */
  */
 export function handleOrderButtons(order) {
 export function handleOrderButtons(order) {
-	order.buttons = [];
-	if (order.type === 3) {
-		// 查看拼团
-		order.buttons.push('combination');
-	}
-	if (order.status === 20) {
-		// 确认收货
-		order.buttons.push('confirm');
-	}
-	if (order.logisticsId > 0) {
-		// 查看物流
-		order.buttons.push('express');
-	}
-	if (order.status === 0) {
-		// 取消订单 / 发起支付
-		order.buttons.push('cancel');
-		order.buttons.push('pay');
-	}
-	if (order.status === 30 && !order.commentStatus) {
-		// 发起评价
-		order.buttons.push('comment');
-	}
-	if (order.status === 40) {
-		// 删除订单
-		order.buttons.push('delete');
-	}
+  order.buttons = [];
+  if (order.type === 3) {
+    // 查看拼团
+    order.buttons.push('combination');
+  }
+  if (order.status === 20) {
+    // 确认收货
+    order.buttons.push('confirm');
+  }
+  if (order.logisticsId > 0) {
+    // 查看物流
+    order.buttons.push('express');
+  }
+  if (order.status === 0) {
+    // 取消订单 / 发起支付
+    order.buttons.push('cancel');
+    order.buttons.push('pay');
+  }
+  if (order.status === 30 && !order.commentStatus) {
+    // 发起评价
+    order.buttons.push('comment');
+  }
+  if (order.status === 40) {
+    // 删除订单
+    order.buttons.push('delete');
+  }
 }
 }
 
 
 /**
 /**
@@ -204,31 +200,31 @@ export function handleOrderButtons(order) {
  * @param afterSale 售后
  * @param afterSale 售后
  */
  */
 export function formatAfterSaleStatus(afterSale) {
 export function formatAfterSaleStatus(afterSale) {
-	if (afterSale.status === 10) {
-		return '申请售后';
-	}
-	if (afterSale.status === 20) {
-		return '商品待退货';
-	}
-	if (afterSale.status === 30) {
-		return '商家待收货';
-	}
-	if (afterSale.status === 40) {
-		return '等待退款';
-	}
-	if (afterSale.status === 50) {
-		return '退款成功';
-	}
-	if (afterSale.status === 61) {
-		return '买家取消';
-	}
-	if (afterSale.status === 62) {
-		return '商家拒绝';
-	}
-	if (afterSale.status === 63) {
-		return '商家拒收货';
-	}
-	return '未知状态';
+  if (afterSale.status === 10) {
+    return '申请售后';
+  }
+  if (afterSale.status === 20) {
+    return '商品待退货';
+  }
+  if (afterSale.status === 30) {
+    return '商家待收货';
+  }
+  if (afterSale.status === 40) {
+    return '等待退款';
+  }
+  if (afterSale.status === 50) {
+    return '退款成功';
+  }
+  if (afterSale.status === 61) {
+    return '买家取消';
+  }
+  if (afterSale.status === 62) {
+    return '商家拒绝';
+  }
+  if (afterSale.status === 63) {
+    return '商家拒收货';
+  }
+  return '未知状态';
 }
 }
 
 
 /**
 /**
@@ -237,31 +233,31 @@ export function formatAfterSaleStatus(afterSale) {
  * @param afterSale 售后
  * @param afterSale 售后
  */
  */
 export function formatAfterSaleStatusDescription(afterSale) {
 export function formatAfterSaleStatusDescription(afterSale) {
-	if (afterSale.status === 10) {
-		return '退款申请待商家处理';
-	}
-	if (afterSale.status === 20) {
-		return '请退货并填写物流信息';
-	}
-	if (afterSale.status === 30) {
-		return '退货退款申请待商家处理';
-	}
-	if (afterSale.status === 40) {
-		return '等待退款';
-	}
-	if (afterSale.status === 50) {
-		return '退款成功';
-	}
-	if (afterSale.status === 61) {
-		return '退款关闭';
-	}
-	if (afterSale.status === 62) {
-		return `商家不同意退款申请,拒绝原因:${afterSale.auditReason}`;
-	}
-	if (afterSale.status === 63) {
-		return `商家拒绝收货,不同意退款,拒绝原因:${afterSale.auditReason}`;
-	}
-	return '未知状态';
+  if (afterSale.status === 10) {
+    return '退款申请待商家处理';
+  }
+  if (afterSale.status === 20) {
+    return '请退货并填写物流信息';
+  }
+  if (afterSale.status === 30) {
+    return '退货退款申请待商家处理';
+  }
+  if (afterSale.status === 40) {
+    return '等待退款';
+  }
+  if (afterSale.status === 50) {
+    return '退款成功';
+  }
+  if (afterSale.status === 61) {
+    return '退款关闭';
+  }
+  if (afterSale.status === 62) {
+    return `商家不同意退款申请,拒绝原因:${afterSale.auditReason}`;
+  }
+  if (afterSale.status === 63) {
+    return `商家拒绝收货,不同意退款,拒绝原因:${afterSale.auditReason}`;
+  }
+  return '未知状态';
 }
 }
 
 
 /**
 /**
@@ -270,15 +266,15 @@ export function formatAfterSaleStatusDescription(afterSale) {
  * @param afterSale 售后
  * @param afterSale 售后
  */
  */
 export function handleAfterSaleButtons(afterSale) {
 export function handleAfterSaleButtons(afterSale) {
-	afterSale.buttons = [];
-	if ([10, 20, 30].includes(afterSale.status)) {
-		// 取消订单
-		afterSale.buttons.push('cancel');
-	}
-	if (afterSale.status === 20) {
-		// 退货信息
-		afterSale.buttons.push('delivery');
-	}
+  afterSale.buttons = [];
+  if ([10, 20, 30].includes(afterSale.status)) {
+    // 取消订单
+    afterSale.buttons.push('cancel');
+  }
+  if (afterSale.status === 20) {
+    // 退货信息
+    afterSale.buttons.push('delivery');
+  }
 }
 }
 
 
 /**
 /**
@@ -288,28 +284,28 @@ export function handleAfterSaleButtons(afterSale) {
  * @return {{s: string, ms: number, h: string, m: string}} 持续时间
  * @return {{s: string, ms: number, h: string, m: string}} 持续时间
  */
  */
 export function useDurationTime(toTime, fromTime = '') {
 export function useDurationTime(toTime, fromTime = '') {
-	toTime = getDayjsTime(toTime);
-	if (fromTime === '') {
-		fromTime = dayjs();
-	}
-	let duration = ref(toTime - fromTime);
-	if (duration.value > 0) {
-		setTimeout(() => {
-			if (duration.value > 0) {
-				duration.value -= 1000;
-			}
-		}, 1000);
-	}
+  toTime = getDayjsTime(toTime);
+  if (fromTime === '') {
+    fromTime = dayjs();
+  }
+  let duration = ref(toTime - fromTime);
+  if (duration.value > 0) {
+    setTimeout(() => {
+      if (duration.value > 0) {
+        duration.value -= 1000;
+      }
+    }, 1000);
+  }
 
 
-	let durationTime = dayjs.duration(duration.value);
-	return {
-		h: (durationTime.months() * 30 * 24 + durationTime.days() * 24 + durationTime.hours())
-			.toString()
-			.padStart(2, '0'),
-		m: durationTime.minutes().toString().padStart(2, '0'),
-		s: durationTime.seconds().toString().padStart(2, '0'),
-		ms: durationTime.$ms,
-	};
+  let durationTime = dayjs.duration(duration.value);
+  return {
+    h: (durationTime.months() * 30 * 24 + durationTime.days() * 24 + durationTime.hours())
+      .toString()
+      .padStart(2, '0'),
+    m: durationTime.minutes().toString().padStart(2, '0'),
+    s: durationTime.seconds().toString().padStart(2, '0'),
+    ms: durationTime.$ms,
+  };
 }
 }
 
 
 /**
 /**
@@ -318,19 +314,19 @@ export function useDurationTime(toTime, fromTime = '') {
  * @return {dayjs.Dayjs}
  * @return {dayjs.Dayjs}
  */
  */
 function getDayjsTime(time) {
 function getDayjsTime(time) {
-	time = time.toString();
-	if (time.indexOf('-') > 0) {
-		// 'date'
-		return dayjs(time);
-	}
-	if (time.length > 10) {
-		// 'timestamp'
-		return dayjs(parseInt(time));
-	}
-	if (time.length === 10) {
-		// 'unixTime'
-		return dayjs.unix(parseInt(time));
-	}
+  time = time.toString();
+  if (time.indexOf('-') > 0) {
+    // 'date'
+    return dayjs(time);
+  }
+  if (time.length > 10) {
+    // 'timestamp'
+    return dayjs(parseInt(time));
+  }
+  if (time.length === 10) {
+    // 'unixTime'
+    return dayjs.unix(parseInt(time));
+  }
 }
 }
 
 
 /**
 /**
@@ -340,7 +336,28 @@ 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);
+}
+
+/**
+ * 将分转成元
+ *
+ * 如果没有小数点,则不展示小数点部分
+ *
+ * @param price 分,例如说 100 分
+ * @returns {string} 元,例如说 1 元
+ */
+export function fen2yuanSimple(price) {
+  return fen2yuan(price).replace(/\.?0+$/, '');
+}
+
+/**
+ * 将折扣百分比转化为“打x者”的 x 部分
+ *
+ * @param discountPercent
+ */
+export function formatDiscountPercent(discountPercent) {
+  return (discountPercent / 10.0).toFixed(1).replace(/\.?0+$/, '');
 }
 }
 
 
 /**
 /**
@@ -358,92 +375,125 @@ export function fen2yuan(price) {
  * @param skus 商品 SKU 数组
  * @param skus 商品 SKU 数组
  */
  */
 export function convertProductPropertyList(skus) {
 export function convertProductPropertyList(skus) {
-	let result = [];
-	for (const sku of skus) {
-		if (!sku.properties) {
-			continue;
-		}
-		for (const property of sku.properties) {
-			// ① 先处理属性
-			let resultProperty = result.find((item) => item.id === property.propertyId);
-			if (!resultProperty) {
-				resultProperty = {
-					id: property.propertyId,
-					name: property.propertyName,
-					values: [],
-				};
-				result.push(resultProperty);
-			}
-			// ② 再处理属性值
-			let resultValue = resultProperty.values.find((item) => item.id === property.valueId);
-			if (!resultValue) {
-				resultProperty.values.push({
-					id: property.valueId,
-					name: property.valueName,
-				});
-			}
-		}
-	}
-	return result;
+  let result = [];
+  for (const sku of skus) {
+    if (!sku.properties) {
+      continue;
+    }
+    for (const property of sku.properties) {
+      // ① 先处理属性
+      let resultProperty = result.find((item) => item.id === property.propertyId);
+      if (!resultProperty) {
+        resultProperty = {
+          id: property.propertyId,
+          name: property.propertyName,
+          values: [],
+        };
+        result.push(resultProperty);
+      }
+      // ② 再处理属性值
+      let resultValue = resultProperty.values.find((item) => item.id === property.valueId);
+      if (!resultValue) {
+        resultProperty.values.push({
+          id: property.valueId,
+          name: property.valueName,
+        });
+      }
+    }
+  }
+  return result;
 }
 }
 
 
 export function appendSettlementProduct(spus, settlementInfos) {
 export function appendSettlementProduct(spus, settlementInfos) {
-	if (!settlementInfos || settlementInfos.length === 0) {
-		return;
-	}
-	for (const spu of spus) {
-		const settlementInfo = settlementInfos.find((info) => info.spuId === spu.id);
-		if (!settlementInfo) {
-			return;
-		}
-		// 选择价格最小的 SKU 设置到 SPU 上
-		const settlementSku = settlementInfo.skus
-			.filter((sku) => sku.promotionPrice > 0)
-			.reduce((prev, curr) => (prev.promotionPrice < curr.promotionPrice ? prev : curr));
-		if (settlementSku) {
-			spu.promotionType = settlementSku.promotionType;
-			spu.promotionPrice = settlementSku.promotionPrice;
-		}
-		// 设置【满减送】活动
-		if (settlementInfo.rewardActivity) {
-			spu.rewardActivity = settlementInfo.rewardActivity;
-		}
-	}
+  if (!settlementInfos || settlementInfos.length === 0) {
+    return;
+  }
+  for (const spu of spus) {
+    const settlementInfo = settlementInfos.find((info) => info.spuId === spu.id);
+    if (!settlementInfo) {
+      return;
+    }
+    // 选择价格最小的 SKU 设置到 SPU 上
+    const settlementSku = settlementInfo.skus
+      .filter((sku) => sku.promotionPrice > 0)
+      .reduce((prev, curr) => (prev.promotionPrice < curr.promotionPrice ? prev : curr));
+    if (settlementSku) {
+      spu.promotionType = settlementSku.promotionType;
+      spu.promotionPrice = settlementSku.promotionPrice;
+    }
+    // 设置【满减送】活动
+    if (settlementInfo.rewardActivity) {
+      spu.rewardActivity = settlementInfo.rewardActivity;
+    }
+  }
 }
 }
 
 
-//处理促销信息
-export function handeleData(array) {
-	const array2 = ref([{
-			name: '满减',
-			value: []
-		},
-		{
-			name: '赠品',
-			value: []
-		},
-		{
-			name: '包邮',
-			value: []
-		}
-	]);
+// 获得满减送活动的规则描述(group)
+export function getRewardActivityRuleGroupDescriptions(activity) {
+  if (!activity || !activity.rules || activity.rules.length === 0) {
+    return [];
+  }
+  const result = [
+    { name: '满减', values: [] },
+    { name: '赠品', values: [] },
+    { name: '包邮', values: [] },
+  ];
+  activity.rules.forEach((rule) => {
+    const conditionTypeStr =
+      activity.conditionType === 10 ? `满 ${fen2yuanSimple(rule.limit)} 元` : `满 ${rule.limit} 件`;
+    // 满减
+    if (rule.limit) {
+      result[0].values.push(`${conditionTypeStr} 减 ${fen2yuanSimple(rule.discountPrice)} 元`);
+    }
+    // 赠品
+    if (rule.point || (rule.giveCouponTemplateCounts && rule.giveCouponTemplateCounts.length > 0)) {
+      let tips = [];
+      if (rule.point) {
+        tips.push(`送 ${rule.point} 积分`);
+      }
+      if (rule.giveCouponTemplateCounts && rule.giveCouponTemplateCounts.length > 0) {
+        tips.push(`送 ${rule.giveCouponTemplateCounts.length} 张优惠券`);
+      }
+      result[1].values.push(`${conditionTypeStr} ${tips.join('、')}`);
+    }
+    // 包邮
+    if (rule.freeDelivery) {
+      result[2].values.push(`${conditionTypeStr} 包邮`);
+    }
+  });
+  // 移除 values 为空的元素
+  result.forEach((item) => {
+    if (item.values.length === 0) {
+      result.splice(result.indexOf(item), 1);
+    }
+  });
+  return result;
+}
 
 
-	array.forEach(item => {
-		Object.entries(item).forEach(([key, value]) => {
-			const type = parseInt(key);
-			switch (type) {
-				case 1:
-					array2.value[0].value.push(value); // 满减
-					break;
-				case 2:
-					array2.value[1].value.push(value); // 满送
-					break;
-				case 3:
-					array2.value[2].value.push(value); // 包邮
-					break;
-				default:
-					break;
-			}
-		});
-	});
-	return array2
-}
+// 获得满减送活动的规则描述(item)
+export function getRewardActivityRuleItemDescriptions(activity) {
+  if (!activity || !activity.rules || activity.rules.length === 0) {
+    return [];
+  }
+  const result = [];
+  activity.rules.forEach((rule) => {
+    const conditionTypeStr =
+      activity.conditionType === 10 ? `满${fen2yuanSimple(rule.limit)}元` : `满${rule.limit}件`;
+    // 满减
+    if (rule.limit) {
+      result.push(`${conditionTypeStr}减${fen2yuanSimple(rule.discountPrice)}元`);
+    }
+    // 赠品
+    if (rule.point) {
+      result.push(`${conditionTypeStr}送${rule.point}积分`);
+    }
+    if (rule.giveCouponTemplateCounts && rule.giveCouponTemplateCounts.length > 0) {
+      result.push(`${conditionTypeStr}送${rule.giveCouponTemplateCounts.length}张优惠券`);
+    }
+    // 包邮
+    if (rule.freeDelivery) {
+      result.push(`${conditionTypeStr}包邮`);
+    }
+  });
+  return result;
+}