潘志宝
6 天以前 ca22cdd5550cfa0defb0f430c538698182cdaec1
提交 | 用户 | 时间
820397 1 <template>
9259c2 2   <div :class="`box-content min-h-30px w-full flex flex-row flex-wrap`" ref="containerRef">
820397 3     <div
9259c2 4       class="relative box-content flex flex-row flex-wrap overflow-hidden bg-white"
820397 5       :style="{
9259c2 6         ...calculateSpace(index),
H 7         ...calculateWidth(),
8         borderTopLeftRadius: `${property.borderRadiusTop}px`,
9         borderTopRightRadius: `${property.borderRadiusTop}px`,
10         borderBottomLeftRadius: `${property.borderRadiusBottom}px`,
11         borderBottomRightRadius: `${property.borderRadiusBottom}px`
820397 12       }"
9259c2 13       v-for="(spu, index) in spuList"
H 14       :key="index"
820397 15     >
9259c2 16       <!-- 角标 -->
H 17       <div v-if="property.badge.show" class="absolute left-0 top-0 z-1 items-center justify-center">
18         <el-image fit="cover" :src="property.badge.imgUrl" class="h-26px w-38px" />
19       </div>
20       <!-- 商品封面图 -->
820397 21       <div
9259c2 22         :class="[
H 23           'h-140px',
24           {
25             'w-full': property.layoutType !== 'oneColSmallImg',
26             'w-140px': property.layoutType === 'oneColSmallImg'
27           }
28         ]"
820397 29       >
9259c2 30         <el-image fit="cover" class="h-full w-full" :src="spu.picUrl" />
H 31       </div>
32       <div
33         :class="[
34           ' flex flex-col gap-8px p-8px box-border',
35           {
36             'w-full': property.layoutType !== 'oneColSmallImg',
37             'w-[calc(100%-140px-16px)]': property.layoutType === 'oneColSmallImg'
38           }
39         ]"
40       >
41         <!-- 商品名称 -->
820397 42         <div
9259c2 43           v-if="property.fields.name.show"
820397 44           :class="[
9259c2 45             'text-14px ',
820397 46             {
9259c2 47               truncate: property.layoutType !== 'oneColSmallImg',
H 48               'overflow-ellipsis line-clamp-2': property.layoutType === 'oneColSmallImg'
820397 49             }
H 50           ]"
9259c2 51           :style="{ color: property.fields.name.color }"
820397 52         >
9259c2 53           {{ spu.name }}
H 54         </div>
55         <!-- 商品简介 -->
56         <div
57           v-if="property.fields.introduction.show"
58           class="truncate text-12px"
59           :style="{ color: property.fields.introduction.color }"
60         >
61           {{ spu.introduction }}
62         </div>
63         <div>
64           <!-- 价格 -->
65           <span
66             v-if="property.fields.price.show"
67             class="text-16px"
68             :style="{ color: property.fields.price.color }"
820397 69           >
9259c2 70             ¥{{ fenToYuan(spu.price || Infinity) }}
H 71           </span>
72           <!-- 市场价 -->
73           <span
74             v-if="property.fields.marketPrice.show && spu.marketPrice"
75             class="ml-4px text-10px line-through"
76             :style="{ color: property.fields.marketPrice.color }"
77             >¥{{ fenToYuan(spu.marketPrice) }}</span
78           >
79         </div>
80         <div class="text-12px">
81           <!-- 销量 -->
82           <span
83             v-if="property.fields.salesCount.show"
84             :style="{ color: property.fields.salesCount.color }"
85           >
86             已售{{ (spu.salesCount || 0) + (spu.virtualSalesCount || 0) }}件
87           </span>
88           <!-- 库存 -->
89           <span v-if="property.fields.stock.show" :style="{ color: property.fields.stock.color }">
90             库存{{ spu.stock || 0 }}
91           </span>
820397 92         </div>
H 93       </div>
9259c2 94       <!-- 购买按钮 -->
H 95       <div class="absolute bottom-8px right-8px">
96         <!-- 文字按钮 -->
97         <span
98           v-if="property.btnBuy.type === 'text'"
99           class="rounded-full p-x-12px p-y-4px text-12px text-white"
100           :style="{
101             background: `linear-gradient(to right, ${property.btnBuy.bgBeginColor}, ${property.btnBuy.bgEndColor}`
102           }"
103         >
104           {{ property.btnBuy.text }}
105         </span>
106         <!-- 图片按钮 -->
107         <el-image
108           v-else
109           class="h-28px w-28px rounded-full"
110           fit="cover"
111           :src="property.btnBuy.imgUrl"
112         />
113       </div>
820397 114     </div>
9259c2 115   </div>
820397 116 </template>
H 117 <script setup lang="ts">
118 import { PromotionSeckillProperty } from './config'
119 import * as ProductSpuApi from '@/api/mall/product/spu'
120 import * as SeckillActivityApi from '@/api/mall/promotion/seckill/seckillActivity'
9259c2 121 import { fenToYuan } from '@/utils'
820397 122
9259c2 123 /** 秒杀卡片 */
820397 124 defineOptions({ name: 'PromotionSeckill' })
H 125 // 定义属性
126 const props = defineProps<{ property: PromotionSeckillProperty }>()
127 // 商品列表
128 const spuList = ref<ProductSpuApi.Spu[]>([])
9259c2 129 const spuIdList = ref<number[]>([])
H 130 const seckillActivityList = ref<SeckillActivityApi.SeckillActivityVO[]>([])
131
820397 132 watch(
9259c2 133   () => props.property.activityIds,
820397 134   async () => {
9259c2 135     try {
H 136       // 新添加的秒杀组件,是没有活动ID的
137       const activityIds = props.property.activityIds
138       // 检查活动ID的有效性
139       if (Array.isArray(activityIds) && activityIds.length > 0) {
140         // 获取秒杀活动详情列表
141         seckillActivityList.value =
142           await SeckillActivityApi.getSeckillActivityListByIds(activityIds)
143
144         // 获取秒杀活动的 SPU 详情列表
145         spuList.value = []
146         spuIdList.value = seckillActivityList.value
147           .map((activity) => activity.spuId)
148           .filter((spuId): spuId is number => typeof spuId === 'number')
149         if (spuIdList.value.length > 0) {
150           spuList.value = await ProductSpuApi.getSpuDetailList(spuIdList.value)
151         }
152
153         // 更新 SPU 的最低价格
154         seckillActivityList.value.forEach((activity) => {
155           // 匹配spuId
156           const spu = spuList.value.find((spu) => spu.id === activity.spuId)
157           if (spu) {
158             // 赋值活动价格,哪个最便宜就赋值哪个
159             spu.price = Math.min(activity.seckillPrice || Infinity, spu.price || Infinity)
160           }
161         })
162       }
163     } catch (error) {
164       console.error('获取秒杀活动细节或 SPU 细节时出错:', error)
165     }
820397 166   },
H 167   {
168     immediate: true,
169     deep: true
170   }
171 )
9259c2 172
H 173 /**
174  * 计算商品的间距
175  * @param index 商品索引
176  */
177 const calculateSpace = (index: number) => {
178   // 商品的列数
179   const columns = props.property.layoutType === 'twoCol' ? 2 : 1
180   // 第一列没有左边距
181   const marginLeft = index % columns === 0 ? '0' : props.property.space + 'px'
182   // 第一行没有上边距
183   const marginTop = index < columns ? '0' : props.property.space + 'px'
184
185   return { marginLeft, marginTop }
186 }
187
820397 188 // 容器
H 189 const containerRef = ref()
9259c2 190 // 计算商品的宽度
H 191 const calculateWidth = () => {
192   let width = '100%'
193   // 双列时每列的宽度为:(总宽度 - 间距)/ 2
194   if (props.property.layoutType === 'twoCol') {
195     width = `${(containerRef.value.offsetWidth - props.property.space) / 2}px`
196   }
197   return { width }
198 }
820397 199 </script>
H 200
201 <style scoped lang="scss"></style>