Files

488 lines
10 KiB
Vue
Raw Normal View History

2023-10-11 11:27:47 +08:00
<template>
<view
class="goods"
:class="[list && 'goods-list',hasFirst && 'goods-first']"
2023-11-14 17:21:03 +08:00
@tap="toDetail"
2023-10-11 11:27:47 +08:00
>
<view
2023-11-14 17:21:03 +08:00
class="goods-header"
2023-10-11 11:27:47 +08:00
>
<view class="goods-thumb">
<LazyImage
:unique="data.id"
2023-11-14 17:21:03 +08:00
:src="data.image"
class="goods-thumb-img"
mode="aspectFit"
2023-10-11 11:27:47 +08:00
/>
</view>
</view>
<view class="goods-content">
<view>
<view
class="goods-storeName"
>{{ data.storeName }}
</view>
<view
class="buy-progress-first"
v-if="hasFirst && buyProgress">
<uv-line-progress
activeColor="#EE6D46"
inactiveColor="#E6E6E6"
height="14rpx"
:percentage="percentageNum"
:showText="false"
/>
<text class="text">已售{{ percentage }}</text>
</view>
2023-11-14 17:21:03 +08:00
</view>
2023-10-11 11:27:47 +08:00
<view
2023-11-14 17:21:03 +08:00
class="goods-list-model"
v-if="selectModel"
2023-10-11 11:27:47 +08:00
>
<div
2023-11-14 17:21:03 +08:00
class="goods-list-model-border"
@tap.stop="handleOpenSelect"
2023-10-11 11:27:47 +08:00
>
<view class="goods-list-model-label">{{ data.attrInfo.sku }}</view>
<view class="goods-list-model-action icon">
2023-11-22 18:55:55 +08:00
<image :src="goodsArrowsIcon" />
2023-10-11 11:27:47 +08:00
</view>
</div>
</view>
<view
2023-11-14 17:21:03 +08:00
class="goods-list-model-info"
v-if="model"
2023-10-11 11:27:47 +08:00
>
<view class="goods-list-model-label">{{ data.attrInfo.sku }}</view>
</view>
<view>
<view class="goods-info">
<view class="goods-info-left">
<view
class="goods-desc"
v-if="groupBuy"
>{{ data.person }}人团
2023-10-11 11:27:47 +08:00
</view>
<view
class="goods-price-row"
2023-10-11 11:27:47 +08:00
>
<view class="goods-price">
¥{{ data.campaignPrice || data.price }}
</view>
<view
class="goods-price goods-price-original"
v-if="original"
>
¥{{ data.otPrice || data.originalPrice }}
</view>
2023-10-11 11:27:47 +08:00
</view>
</view>
<view class="goods-info-action">
<view class="goods-info-action-btn">
<slot name="action"></slot>
</view>
<view
v-if="stock"
class="goods-info-action-desc"
2023-11-14 17:21:03 +08:00
>
<text v-if="data.stock">仅剩{{ data.stock }}</text>
<text v-else>库存不足</text>
2023-10-11 11:27:47 +08:00
</view>
<view
class="buy-num"
v-if="purchase"
>
<view class="buy-num-info-desc">
x{{ purchase }}
</view>
</view>
<uv-button
2024-02-22 18:37:23 +08:00
class="button"
round
block
type="primary"
v-if="groupBuy"
>
立刻拼团
</uv-button>
2023-10-11 11:27:47 +08:00
</view>
</view>
<view
class="buy-progress"
v-if="!hasFirst && buyProgress">
2023-10-11 11:27:47 +08:00
<view class="buy-progress-info">
<view
2023-11-14 17:21:03 +08:00
class="buy-progress-info-desc"
v-if="total"
2023-10-11 11:27:47 +08:00
>
限量{{ data.campaignTotal || data.total }}
2023-10-11 11:27:47 +08:00
</view>
<uv-line-progress
activeColor="#EE6D46"
inactiveColor="#E6E6E6"
height="14rpx"
:percentage="percentageNum"
2023-11-14 17:21:03 +08:00
:showText="false"
2023-10-11 11:27:47 +08:00
/>
</view>
<view class="buy-progress-action">
<uv-button
2023-11-14 17:21:03 +08:00
round
block
type="primary"
2023-10-11 11:27:47 +08:00
>
立即抢购
</uv-button>
</view>
</view>
</view>
</view>
<good-attr-select
2023-11-14 17:21:03 +08:00
ref="selectAttrPanel"
:id="data.id"
@select="handleSelectAttr"
2023-10-11 11:27:47 +08:00
/>
</view>
</template>
<script setup>
import { computed, ref } from 'vue'
2023-11-14 17:21:03 +08:00
import { useRouter } from "@/hooks/useRouter";
2023-11-22 18:55:55 +08:00
import { goodsArrowsIcon } from "@/utils/images";
import LazyImage from '@/components/LazyImage/index.vue'
2023-11-14 17:21:03 +08:00
const props = defineProps(['data', 'groupBuy', 'original', 'stock', 'list', 'buyProgress', 'total', 'selectModel', 'model', 'purchase', 'link', 'price', 'hasFirst'])
2023-10-11 11:27:47 +08:00
// 列表模式
const list = ref(props.list !== undefined)
// 是否团购
const groupBuy = ref(props.groupBuy)
// 剩余数量
const stock = ref(props.stock)
2023-10-11 11:27:47 +08:00
// 限量多少件
const total = ref(props.total)
2023-10-11 11:27:47 +08:00
// 显示购买进度
const buyProgress = ref(props.buyProgress)
// 选择规格
const selectModel = ref(props.selectModel !== undefined)
// 显示规格
const model = ref(props.model !== undefined)
// 购买数量
const purchase = ref(props.purchase)
2023-11-14 17:21:03 +08:00
// 购买价格
const price = ref(props.price)
2023-10-11 11:27:47 +08:00
// 原价
const original = ref(props.original)
// 小尺寸
const selectAttrPanel = ref(null)
// 链接
2023-10-11 11:27:47 +08:00
const link = ref(props.link !== undefined)
// 是否有首条
const hasFirst = ref(props.hasFirst)
2023-11-14 17:21:03 +08:00
const {push} = useRouter()
2023-10-11 11:27:47 +08:00
const toDetail = () => {
2023-11-14 17:21:03 +08:00
if (!link.value) {
return
}
push({url: '/pages/goodsDetail/goodsDetail'}, {data: {id: props.data.id, skuId: props.data.skuId}})
2023-10-11 11:27:47 +08:00
}
const handleOpenSelect = () => {
selectAttrPanel.value.open()
}
const handleSelectAttr = () => {
}
const percentageNum = computed(() => {
const total = props.data.campaignTotal || props.data.total
const stock = props.data.campaignStock || props.data.stock
return (total - stock) / total * 100
})
const percentage = computed(() => {
const total = props.data.campaignTotal || props.data.total
const stock = props.data.campaignStock || props.data.stock
return Math.floor((total - stock) / total * 100).toFixed(0) + '%'
})
2023-10-11 11:27:47 +08:00
</script>
2023-11-14 17:21:03 +08:00
<style lang="scss">
2023-10-11 11:27:47 +08:00
.goods {
position: relative;
&-thumb {
width: 335rpx;
height: 335rpx;
2023-10-11 11:27:47 +08:00
&-img {
width: 100%;
2023-10-11 11:27:47 +08:00
}
}
&-thumb {
background: #FAFAFA;
}
2023-11-14 17:21:03 +08:00
&-content {
padding: 20rpx;
2023-11-14 17:21:03 +08:00
}
2023-10-11 11:27:47 +08:00
&-storeName {
line-height: 40rpx;
font-size: 28rpx;
font-weight: 500;
color: #333333;
2023-11-14 17:21:03 +08:00
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
2023-11-14 17:21:03 +08:00
-webkit-box-orient: vertical;
margin-bottom: 7rpx;
2023-10-11 11:27:47 +08:00
}
.buy-progress-first {
display: flex;
align-items: center;
margin-top: 20rpx;
2023-10-11 11:27:47 +08:00
.text {
font-size: 24rpx;
color: #999999;
margin-left: 20rpx;
}
}
2023-10-11 11:27:47 +08:00
// 进度条
::v-deep .uv-line-progress {
border-radius: 0;
&__background {
border-radius: 0;
2023-10-11 11:27:47 +08:00
}
&__line {
border-radius: 0;
2023-10-11 11:27:47 +08:00
}
}
2023-10-11 11:27:47 +08:00
&-price {
line-height: 42rpx;
font-size: 30rpx;
color: #EE6D46;
&-row {
display: flex;
align-items: flex-end;
2023-10-11 11:27:47 +08:00
}
//&-primary {
// line-height: 42rpx;
// font-size: 30rpx;
// color: #EE6D46;
//}
//
//&-default {
// line-height: 42rpx;
// font-size: 30rpx;
// color: #EE6D46;
//}
2023-10-11 11:27:47 +08:00
&-original {
margin-left: 9rpx;
line-height: 28rpx;
font-size: 20rpx;
color: #999999;
text-decoration: line-through;
}
}
&-desc {
line-height: 33rpx;
font-size: 24rpx;
color: #999999;
}
&-info {
display: flex;
align-items: flex-end;
justify-content: space-between;
margin-bottom: 3rpx;
2023-10-11 11:27:47 +08:00
&-action {
display: flex;
align-items: center;
justify-content: center;
2023-10-11 11:27:47 +08:00
2024-02-22 18:37:23 +08:00
.button {
flex-shrink: 0;
white-space: nowrap;
}
2023-10-11 11:27:47 +08:00
&-desc {
line-height: 28rpx;
font-size: 20rpx;
color: #999999;
}
}
}
::v-deep .uv-button {
width: 140rpx;
height: 60rpx;
padding: 0;
font-size: 24rpx;
2023-10-11 11:27:47 +08:00
}
&-list, &-first {
2023-10-11 11:27:47 +08:00
display: flex;
flex-direction: row;
padding: 20rpx 34rpx 20rpx 20rpx;
2023-10-11 11:27:47 +08:00
box-sizing: border-box;
width: 100%;
.goods {
&-thumb {
margin-bottom: 0;
width: 270rpx;
height: 270rpx;
2023-10-11 11:27:47 +08:00
&-img {
width: 100%;
height: 100%;
display: block;
}
}
&-content {
padding: 0;
2023-11-14 17:21:03 +08:00
margin-left: 40rpx;
2023-10-11 11:27:47 +08:00
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
2023-11-14 17:21:03 +08:00
width: 0;
2023-10-11 11:27:47 +08:00
}
&-storeName {
-webkit-line-clamp: 2;
}
&-info {
.goods-price {
font-size: 34rpx;
}
.goods-price-original {
font-size: 20rpx;
}
}
2023-10-11 11:27:47 +08:00
}
&-model {
display: flex;
margin-bottom: 28rpx;
&-border {
display: flex;
align-items: center;
height: 40rpx;
border: 1px solid #CCCCCC;
opacity: 1;
border-radius: 0rpx;
padding: 0 10rpx;
}
&-label {
line-height: 38rpx;
font-size: 24rpx;
color: #999999;
margin-right: 10rpx;
2023-11-17 20:55:32 +08:00
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
2023-10-11 11:27:47 +08:00
}
&-value {
line-height: 38rpx;
font-size: 24rpx;
color: #333333;
margin-right: 10rpx;
2023-11-17 20:55:32 +08:00
display: -webkit-box;
2023-10-11 11:27:47 +08:00
}
&-action {
width: 11rpx;
height: 7rpx;
}
}
}
&-model {
display: inline-flex;
align-items: center;
width: auto;
height: 40rpx;
border: 1px solid #CCCCCC;
opacity: 1;
border-radius: 0rpx;
padding: 0 10rpx;
margin-bottom: 28rpx;
&-label {
line-height: 38rpx;
font-size: 24rpx;
color: #999999;
}
&-value {
line-height: 38rpx;
font-size: 24rpx;
color: #333333;
margin-right: 10rpx;
}
&-action {
width: 11rpx;
height: 7rpx;
}
}
}
.buy-progress {
display: flex;
align-items: center;
justify-content: space-between;
&-info {
flex: 1;
&-desc {
color: #999999;
font-size: 24rpx;
line-height: 32rpx;
}
}
&-action {
margin-left: 17rpx;
}
}
.buy-num {
&-info-desc {
color: #999999;
font-size: 24rpx;
line-height: 32rpx;
}
}
</style>