From 9259c2235e31708f954a3578bde3c6a7ab9753e8 Mon Sep 17 00:00:00 2001 From: houzhongjian <houzhongyi@126.com> Date: 星期一, 30 十二月 2024 15:51:40 +0800 Subject: [PATCH] 1、工作流相关组件更新 2、偶尔出现退出登录时路由报错的bug导致无法回到登录页面 3、全局配置文件修改,移除VITE_UPLOAD_URL配置等 --- src/components/DiyEditor/components/mobile/PromotionCombination/index.vue | 244 ++++++++++++++++++++++++++++++++---------------- 1 files changed, 160 insertions(+), 84 deletions(-) diff --git a/src/components/DiyEditor/components/mobile/PromotionCombination/index.vue b/src/components/DiyEditor/components/mobile/PromotionCombination/index.vue index fe6f3a8..d41bf1c 100644 --- a/src/components/DiyEditor/components/mobile/PromotionCombination/index.vue +++ b/src/components/DiyEditor/components/mobile/PromotionCombination/index.vue @@ -1,125 +1,201 @@ <template> - <el-scrollbar class="z-1 min-h-30px" wrap-class="w-full" ref="containerRef"> - <!-- 商品网格 --> + <div :class="`box-content min-h-30px w-full flex flex-row flex-wrap`" ref="containerRef"> <div - class="grid overflow-x-auto" + class="relative box-content flex flex-row flex-wrap overflow-hidden bg-white" :style="{ - gridGap: `${property.space}px`, - gridTemplateColumns, - width: scrollbarWidth + ...calculateSpace(index), + ...calculateWidth(), + borderTopLeftRadius: `${property.borderRadiusTop}px`, + borderTopRightRadius: `${property.borderRadiusTop}px`, + borderBottomLeftRadius: `${property.borderRadiusBottom}px`, + borderBottomRightRadius: `${property.borderRadiusBottom}px` }" + v-for="(spu, index) in spuList" + :key="index" > - <!-- 商品 --> + <!-- 角标 --> + <div v-if="property.badge.show" class="absolute left-0 top-0 z-1 items-center justify-center"> + <el-image fit="cover" :src="property.badge.imgUrl" class="h-26px w-38px" /> + </div> + <!-- 商品封面图 --> <div - class="relative box-content flex flex-row flex-wrap overflow-hidden bg-white" - :style="{ - borderTopLeftRadius: `${property.borderRadiusTop}px`, - borderTopRightRadius: `${property.borderRadiusTop}px`, - borderBottomLeftRadius: `${property.borderRadiusBottom}px`, - borderBottomRightRadius: `${property.borderRadiusBottom}px` - }" - v-for="(spu, index) in spuList" - :key="index" + :class="[ + 'h-140px', + { + 'w-full': property.layoutType !== 'oneColSmallImg', + 'w-140px': property.layoutType === 'oneColSmallImg' + } + ]" > - <!-- 角标 --> + <el-image fit="cover" class="h-full w-full" :src="spu.picUrl" /> + </div> + <div + :class="[ + ' flex flex-col gap-8px p-8px box-border', + { + 'w-full': property.layoutType !== 'oneColSmallImg', + 'w-[calc(100%-140px-16px)]': property.layoutType === 'oneColSmallImg' + } + ]" + > + <!-- 商品名称 --> <div - v-if="property.badge.show" - class="absolute left-0 top-0 z-1 items-center justify-center" - > - <el-image fit="cover" :src="property.badge.imgUrl" class="h-26px w-38px" /> - </div> - <!-- 商品封面图 --> - <el-image fit="cover" :src="spu.picUrl" :style="{ width: imageSize, height: imageSize }" /> - <div + v-if="property.fields.name.show" :class="[ - 'flex flex-col gap-8px p-8px box-border', + 'text-14px ', { - 'w-[calc(100%-64px)]': columns === 2, - 'w-full': columns === 3 + truncate: property.layoutType !== 'oneColSmallImg', + 'overflow-ellipsis line-clamp-2': property.layoutType === 'oneColSmallImg' } ]" + :style="{ color: property.fields.name.color }" > - <!-- 商品名称 --> - <div - v-if="property.fields.name.show" - class="truncate text-12px" - :style="{ color: property.fields.name.color }" + {{ spu.name }} + </div> + <!-- 商品简介 --> + <div + v-if="property.fields.introduction.show" + class="truncate text-12px" + :style="{ color: property.fields.introduction.color }" + > + {{ spu.introduction }} + </div> + <div> + <!-- 价格 --> + <span + v-if="property.fields.price.show" + class="text-16px" + :style="{ color: property.fields.price.color }" > - {{ spu.name }} - </div> - <div> - <!-- 商品价格 --> - <span - v-if="property.fields.price.show" - class="text-12px" - :style="{ color: property.fields.price.color }" - > - ¥{{ spu.price }} - </span> - </div> + ¥{{ fenToYuan(spu.price || Infinity) }} + </span> + <!-- 市场价 --> + <span + v-if="property.fields.marketPrice.show && spu.marketPrice" + class="ml-4px text-10px line-through" + :style="{ color: property.fields.marketPrice.color }" + >¥{{ fenToYuan(spu.marketPrice) }}</span + > + </div> + <div class="text-12px"> + <!-- 销量 --> + <span + v-if="property.fields.salesCount.show" + :style="{ color: property.fields.salesCount.color }" + > + 已售{{ (spu.salesCount || 0) + (spu.virtualSalesCount || 0) }}件 + </span> + <!-- 库存 --> + <span v-if="property.fields.stock.show" :style="{ color: property.fields.stock.color }"> + 库存{{ spu.stock || 0 }} + </span> </div> </div> + <!-- 购买按钮 --> + <div class="absolute bottom-8px right-8px"> + <!-- 文字按钮 --> + <span + v-if="property.btnBuy.type === 'text'" + class="rounded-full p-x-12px p-y-4px text-12px text-white" + :style="{ + background: `linear-gradient(to right, ${property.btnBuy.bgBeginColor}, ${property.btnBuy.bgEndColor}` + }" + > + {{ property.btnBuy.text }} + </span> + <!-- 图片按钮 --> + <el-image + v-else + class="h-28px w-28px rounded-full" + fit="cover" + :src="property.btnBuy.imgUrl" + /> + </div> </div> - </el-scrollbar> + </div> </template> <script setup lang="ts"> import { PromotionCombinationProperty } from './config' import * as ProductSpuApi from '@/api/mall/product/spu' import * as CombinationActivityApi from '@/api/mall/promotion/combination/combinationActivity' +import { fenToYuan } from '@/utils' -/** 拼团 */ +/** 拼团卡片 */ defineOptions({ name: 'PromotionCombination' }) // 定义属性 const props = defineProps<{ property: PromotionCombinationProperty }>() // 商品列表 const spuList = ref<ProductSpuApi.Spu[]>([]) +const spuIdList = ref<number[]>([]) +const combinationActivityList = ref<CombinationActivityApi.CombinationActivityVO[]>([]) + watch( - () => props.property.activityId, + () => props.property.activityIds, async () => { - if (!props.property.activityId) return - const activity = await CombinationActivityApi.getCombinationActivity(props.property.activityId) - if (!activity?.spuId) return - spuList.value = [await ProductSpuApi.getSpu(activity.spuId)] + try { + // 新添加的拼团组件,是没有活动ID的 + const activityIds = props.property.activityIds + // 检查活动ID的有效性 + if (Array.isArray(activityIds) && activityIds.length > 0) { + // 获取拼团活动详情列表 + combinationActivityList.value = + await CombinationActivityApi.getCombinationActivityListByIds(activityIds) + + // 获取拼团活动的 SPU 详情列表 + spuList.value = [] + spuIdList.value = combinationActivityList.value + .map((activity) => activity.spuId) + .filter((spuId): spuId is number => typeof spuId === 'number') + if (spuIdList.value.length > 0) { + spuList.value = await ProductSpuApi.getSpuDetailList(spuIdList.value) + } + + // 更新 SPU 的最低价格 + combinationActivityList.value.forEach((activity) => { + // 匹配spuId + const spu = spuList.value.find((spu) => spu.id === activity.spuId) + if (spu) { + // 赋值活动价格,哪个最便宜就赋值哪个 + spu.price = Math.min(activity.combinationPrice || Infinity, spu.price || Infinity) + } + }) + } + } catch (error) { + console.error('获取拼团活动细节或 SPU 细节时出错:', error) + } }, { immediate: true, deep: true } ) -// 手机宽度 -const phoneWidth = ref(375) + +/** + * 计算商品的间距 + * @param index 商品索引 + */ +const calculateSpace = (index: number) => { + // 商品的列数 + const columns = props.property.layoutType === 'twoCol' ? 2 : 1 + // 第一列没有左边距 + const marginLeft = index % columns === 0 ? '0' : props.property.space + 'px' + // 第一行没有上边距 + const marginTop = index < columns ? '0' : props.property.space + 'px' + + return { marginLeft, marginTop } +} + // 容器 const containerRef = ref() -// 商品的列数 -const columns = ref(2) -// 滚动条宽度 -const scrollbarWidth = ref('100%') -// 商品图大小 -const imageSize = ref('0') -// 商品网络列数 -const gridTemplateColumns = ref('') -// 计算布局参数 -watch( - () => [props.property, phoneWidth, spuList.value.length], - () => { - // 计算列数 - columns.value = props.property.layoutType === 'oneCol' ? 1 : 3 - // 每列的宽度为:(总宽度 - 间距 * (列数 - 1))/ 列数 - const productWidth = - (phoneWidth.value - props.property.space * (columns.value - 1)) / columns.value - // 商品图布局:2列时,左右布局 3列时,上下布局 - imageSize.value = columns.value === 2 ? '64px' : `${productWidth}px` - // 指定列数 - gridTemplateColumns.value = `repeat(${columns.value}, auto)` - // 不滚动 - scrollbarWidth.value = '100%' - }, - { immediate: true, deep: true } -) -onMounted(() => { - // 提取手机宽度 - phoneWidth.value = containerRef.value?.wrapRef?.offsetWidth || 375 -}) +// 计算商品的宽度 +const calculateWidth = () => { + let width = '100%' + // 双列时每列的宽度为:(总宽度 - 间距)/ 2 + if (props.property.layoutType === 'twoCol') { + width = `${(containerRef.value.offsetWidth - props.property.space) / 2}px` + } + return { width } +} </script> <style scoped lang="scss"></style> -- Gitblit v1.9.3