160 lines
3.1 KiB
Vue
160 lines
3.1 KiB
Vue
![]() |
<!--
|
|||
|
@name: Activity
|
|||
|
@author: kahu4
|
|||
|
@date: 2024-01-16 14:48
|
|||
|
@description:Activity 活动
|
|||
|
@update: 2024-01-16 14:48
|
|||
|
-->
|
|||
|
<script setup>
|
|||
|
import { computed, onBeforeUnmount, onMounted, ref, toRefs, watch } from "vue";
|
|||
|
import { getTimeAfterNow } from "@/utils/utils";
|
|||
|
|
|||
|
const emits = defineEmits(['timeOver'])
|
|||
|
/**
|
|||
|
* @property {String|Number} price 售卖价格
|
|||
|
* @property {String|Number} oldPrice 划线价格
|
|||
|
* @property {Number} type 组件类型 1、拼团,2、秒杀,3、限时折扣
|
|||
|
* @property {Number} state 活动状态 0-未开始 1-进行中 2-已结束 3-预热
|
|||
|
* @property {Number} time 活动剩余时间
|
|||
|
*/
|
|||
|
const props = defineProps({
|
|||
|
price: {
|
|||
|
type: [String, Number],
|
|||
|
},
|
|||
|
oldPrice: {
|
|||
|
type: [String, Number],
|
|||
|
},
|
|||
|
type: {
|
|||
|
type: Number,
|
|||
|
default: 1
|
|||
|
},
|
|||
|
state: {
|
|||
|
type: Number,
|
|||
|
default: 3
|
|||
|
},
|
|||
|
time: {
|
|||
|
type: Number,
|
|||
|
default: 0
|
|||
|
}
|
|||
|
})
|
|||
|
|
|||
|
const {price, oldPrice, type, state, time} = toRefs(props)
|
|||
|
|
|||
|
// 组件的title
|
|||
|
const componentTitle = computed(() => ['拼团', '秒杀', '限时折扣'][type.value - 1])
|
|||
|
|
|||
|
let interval
|
|||
|
const countDownTime = ref(time.value)
|
|||
|
watch(time, () => {
|
|||
|
countDownTime.value = time.value
|
|||
|
})
|
|||
|
|
|||
|
const countDownStrData = ref({
|
|||
|
hours: '00',
|
|||
|
minutes: '00',
|
|||
|
seconds: '00'
|
|||
|
})
|
|||
|
|
|||
|
/**
|
|||
|
* 开始倒计时
|
|||
|
*/
|
|||
|
function playCountDown() {
|
|||
|
if (countDownTime.value - Date.now() <= 0) return;
|
|||
|
interval = setInterval(() => {
|
|||
|
if (countDownTime.value > 1000) {
|
|||
|
countDownStrData.value = getTimeAfterNow(countDownTime.value)
|
|||
|
} else {
|
|||
|
stopCountDown()
|
|||
|
// 判断状态,活动开始和活动结束
|
|||
|
emits('timeOver')
|
|||
|
}
|
|||
|
}, 1000)
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 停止倒计时
|
|||
|
*/
|
|||
|
function stopCountDown() {
|
|||
|
countDownTime.value = 0
|
|||
|
interval && clearInterval(interval)
|
|||
|
interval = undefined
|
|||
|
}
|
|||
|
|
|||
|
const countDownStr = computed(() => {
|
|||
|
const timeStr = ` ${ countDownStrData.value.hours } : ${ countDownStrData.value.minutes } : ${ countDownStrData.value.seconds }`
|
|||
|
if ([0, 3].includes(state.value)) {
|
|||
|
// 未开始、预热
|
|||
|
return `距开始 ${ timeStr }`
|
|||
|
} else if ([1].includes(state.value)) {
|
|||
|
// 已经开始
|
|||
|
return `距结束 ${ timeStr }`
|
|||
|
}
|
|||
|
})
|
|||
|
|
|||
|
|
|||
|
onMounted(() => {
|
|||
|
playCountDown()
|
|||
|
})
|
|||
|
|
|||
|
onBeforeUnmount(() => {
|
|||
|
stopCountDown()
|
|||
|
})
|
|||
|
|
|||
|
</script>
|
|||
|
|
|||
|
<template>
|
|||
|
<!-- 活动商品 -->
|
|||
|
<view class="price-row">
|
|||
|
<view class="left-col">
|
|||
|
<view class="title">
|
|||
|
{{ componentTitle }}
|
|||
|
</view>
|
|||
|
<view class="price-box">
|
|||
|
<span class="price">
|
|||
|
¥{{ price }}
|
|||
|
</span>
|
|||
|
<span
|
|||
|
v-if="oldPrice"
|
|||
|
class="old-price">
|
|||
|
¥{{ oldPrice }}
|
|||
|
</span>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
<view class="right-col">
|
|||
|
{{ countDownStr }}
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
</template>
|
|||
|
|
|||
|
<style
|
|||
|
lang="scss"
|
|||
|
scoped>
|
|||
|
.price-row {
|
|||
|
width: 100%;
|
|||
|
@include usePadding(30, 30);
|
|||
|
@include useFlex(space-between, flex-end);
|
|||
|
background: $primary-color;
|
|||
|
color: $white-color;
|
|||
|
|
|||
|
.left-col {
|
|||
|
.title {
|
|||
|
font-size: 34rpx;
|
|||
|
}
|
|||
|
|
|||
|
.price-box {
|
|||
|
.price {
|
|||
|
font-size: 50rpx;
|
|||
|
}
|
|||
|
|
|||
|
.old-price {
|
|||
|
font-size: 28rpx;
|
|||
|
text-decoration: line-through;
|
|||
|
margin-left: 15rpx;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
</style>
|