<template>
|
<el-scrollbar class="z-1 min-h-30px" wrap-class="w-full" ref="containerRef">
|
<!-- 商品网格 -->
|
<div
|
class="grid overflow-x-auto"
|
:style="{
|
gridGap: `${property.space}px`,
|
gridTemplateColumns,
|
width: scrollbarWidth
|
}"
|
>
|
<!-- 商品 -->
|
<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"
|
>
|
<!-- 角标 -->
|
<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
|
:class="[
|
'flex flex-col gap-8px p-8px box-border',
|
{
|
'w-[calc(100%-64px)]': columns === 2,
|
'w-full': columns === 3
|
}
|
]"
|
>
|
<!-- 商品名称 -->
|
<div
|
v-if="property.fields.name.show"
|
class="truncate text-12px"
|
:style="{ color: property.fields.name.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>
|
</div>
|
</div>
|
</div>
|
</el-scrollbar>
|
</template>
|
<script setup lang="ts">
|
import { ProductListProperty } from './config'
|
import * as ProductSpuApi from '@/api/mall/product/spu'
|
|
/** 商品栏 */
|
defineOptions({ name: 'ProductList' })
|
// 定义属性
|
const props = defineProps<{ property: ProductListProperty }>()
|
// 商品列表
|
const spuList = ref<ProductSpuApi.Spu[]>([])
|
watch(
|
() => props.property.spuIds,
|
async () => {
|
spuList.value = await ProductSpuApi.getSpuDetailList(props.property.spuIds)
|
},
|
{
|
immediate: true,
|
deep: true
|
}
|
)
|
// 手机宽度
|
const phoneWidth = ref(375)
|
// 容器
|
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 === 'twoCol' ? 2 : 3
|
// 每列的宽度为:(总宽度 - 间距 * (列数 - 1))/ 列数
|
const productWidth =
|
(phoneWidth.value - props.property.space * (columns.value - 1)) / columns.value
|
// 商品图布局:2列时,左右布局 3列时,上下布局
|
imageSize.value = columns.value === 2 ? '64px' : `${productWidth}px`
|
// 根据布局类型,计算行数、列数
|
if (props.property.layoutType === 'horizSwiper') {
|
// 单行显示
|
gridTemplateColumns.value = `repeat(auto-fill, ${productWidth}px)`
|
// 显示滚动条
|
scrollbarWidth.value = `${
|
productWidth * spuList.value.length + props.property.space * (spuList.value.length - 1)
|
}px`
|
} else {
|
// 指定列数
|
gridTemplateColumns.value = `repeat(${columns.value}, auto)`
|
// 不滚动
|
scrollbarWidth.value = '100%'
|
}
|
},
|
{ immediate: true, deep: true }
|
)
|
onMounted(() => {
|
// 提取手机宽度
|
phoneWidth.value = containerRef.value?.wrapRef?.offsetWidth || 375
|
})
|
</script>
|
|
<style scoped lang="scss"></style>
|