<template>
|
<view class="tn-countdown-class tn-countdown">
|
<view
|
v-if="showDays && (hideZeroDay || (!hideZeroDay && d != '00'))"
|
class="tn-countdown__item"
|
:class="[backgroundColorClass]"
|
:style="[itemStyle]"
|
>
|
<view class="tn-countdown__item__time" :class="[fontColorClass]" :style="[letterStyle]">
|
{{ d }}
|
</view>
|
</view>
|
<view
|
v-if="showHours && (hideZeroDay || (!hideZeroDay && d != '00'))"
|
class="tn-countdown__separator"
|
:style="{
|
fontSize: separatorSize + 'rpx',
|
color: separatorColor,
|
paddingBottom: separator === 'en' ? '4rpx' : 0
|
}"
|
>
|
{{ separator === 'en' ? ':' : '天'}}
|
</view>
|
|
<view
|
v-if="showHours"
|
class="tn-countdown__item"
|
:class="[backgroundColorClass]"
|
:style="[itemStyle]"
|
>
|
<view class="tn-countdown__item__time" :class="[fontColorClass]" :style="[letterStyle]">
|
{{ h }}
|
</view>
|
</view>
|
<view
|
v-if="showMinutes"
|
class="tn-countdown__separator"
|
:style="{
|
fontSize: separatorSize + 'rpx',
|
color: separatorColor,
|
paddingBottom: separator === 'en' ? '4rpx' : 0
|
}"
|
>
|
{{ separator === 'en' ? ':' : '时'}}
|
</view>
|
|
<view
|
v-if="showMinutes"
|
class="tn-countdown__item"
|
:class="[backgroundColorClass]"
|
:style="[itemStyle]"
|
>
|
<view class="tn-countdown__item__time" :class="[fontColorClass]" :style="[letterStyle]">
|
{{ m }}
|
</view>
|
</view>
|
<view
|
v-if="showSeconds"
|
class="tn-countdown__separator"
|
:style="{
|
fontSize: separatorSize + 'rpx',
|
color: separatorColor,
|
paddingBottom: separator === 'en' ? '4rpx' : 0
|
}"
|
>
|
{{ separator === 'en' ? ':' : '分'}}
|
</view>
|
|
<view
|
v-if="showSeconds"
|
class="tn-countdown__item"
|
:class="[backgroundColorClass]"
|
:style="[itemStyle]"
|
>
|
<view class="tn-countdown__item__time" :class="[fontColorClass]" :style="[letterStyle]">
|
{{ s }}
|
</view>
|
</view>
|
<view
|
v-if="showSeconds && separator === 'cn'"
|
class="tn-countdown__separator"
|
:style="{
|
fontSize: separatorSize + 'rpx',
|
color: separatorColor,
|
paddingBottom: separator === 'en' ? '4rpx' : 0
|
}"
|
>
|
秒
|
</view>
|
</view>
|
</template>
|
|
<script>
|
import componentsColorMixin from '../../libs/mixin/components_color.js'
|
export default {
|
name: 'tn-count-down',
|
mixins: [componentsColorMixin],
|
props: {
|
// 倒计时时间,秒作为单位
|
timestamp: {
|
type: Number,
|
default: 0
|
},
|
// 是否自动开始
|
autoplay: {
|
type: Boolean,
|
default: true
|
},
|
// 数字框高度
|
height: {
|
type: [String, Number],
|
default: 'auto'
|
},
|
// 分隔符类型
|
// en -> 使用英文的冒号 cn -> 使用中文进行分割
|
separator: {
|
type: String,
|
default: 'en'
|
},
|
// 分割符大小
|
separatorSize: {
|
type: Number,
|
default: 30
|
},
|
// 分隔符颜色
|
separatorColor: {
|
type: String,
|
default: '#080808'
|
},
|
// 是否显示边框
|
showBorder: {
|
type: Boolean,
|
default: false
|
},
|
// 边框颜色
|
borderColor: {
|
type: String,
|
default: '#080808'
|
},
|
// 是否显示秒
|
showSeconds: {
|
type: Boolean,
|
default: true
|
},
|
// 是否显示分
|
showMinutes: {
|
type: Boolean,
|
default: true
|
},
|
// 是否显示时
|
showHours: {
|
type: Boolean,
|
default: true
|
},
|
// 是否显示天
|
showDays: {
|
type: Boolean,
|
default: true
|
},
|
// 如果当天的部分为0时,是否隐藏不显示
|
hideZeroDay: {
|
type: Boolean,
|
default: false
|
}
|
},
|
computed: {
|
// 倒计时item的样式
|
itemStyle() {
|
let style = {}
|
if (this.height) {
|
style.height = this.$t.string.getLengthUnitValue(this.height)
|
style.width = style.height
|
}
|
if (this.showBorder) {
|
style.borderStyle = 'solid'
|
style.borderColor = this.borderColor
|
style.borderWidth = '1rpx'
|
}
|
style.backgroundColor = this.backgroundColorStyle || '#FFFFFF'
|
return style
|
},
|
// 倒计时数字样式
|
letterStyle() {
|
let style = {}
|
style.fontSize = this.fontSizeStyle || '30rpx'
|
style.color = this.fontColorStyle || '#080808'
|
return style
|
}
|
},
|
data() {
|
return {
|
d: '00',
|
h: '00',
|
m: '00',
|
s: '00',
|
// 定时器
|
timer: null,
|
// 记录倒计过程中变化的秒数
|
seconds: 0
|
}
|
},
|
watch: {
|
// 监听时间戳变化
|
timestamp(value) {
|
this.clearTimer()
|
this.start()
|
}
|
},
|
mounted() {
|
// 如果时自动倒计时,加载完成开始计时
|
this.autoplay && this.timestamp && this.start()
|
},
|
beforeDestroy() {
|
this.clearTimer()
|
},
|
methods: {
|
// 开始倒计时
|
start() {
|
// 避免可能出现的倒计时重叠情况
|
this.clearTimer()
|
if (this.timestamp <= 0) return
|
this.seconds = Number(this.timestamp)
|
this.formatTime(this.seconds)
|
this.timer = setInterval(() => {
|
this.seconds--
|
// 发出change事件
|
this.$emit('change', this.seconds)
|
if (this.seconds < 0) {
|
return this.end()
|
}
|
this.formatTime(this.seconds)
|
}, 1000)
|
},
|
// 格式化时间
|
formatTime(seconds) {
|
// 小于等于0的话,结束倒计时
|
seconds <= 0 && this.end()
|
let [day, hour, minute, second] = [0, 0, 0, 0]
|
day = Math.floor(seconds / (60 * 60 * 24))
|
// 如果不显示天,则将天对应的小时计入到小时中
|
// 先把当前的hour计算出来供分和秒使用
|
hour = Math.floor(seconds / (60 * 60)) - (day * 24)
|
let showHour = null
|
if (this.showDays) {
|
showHour = hour
|
} else {
|
// 将天数对应的小时加入到时中进行显示
|
showHour = Math.floor(seconds / (60 * 60))
|
}
|
minute = Math.floor(seconds / 60) - (hour * 60) - (day * 24 * 60)
|
second = Math.floor(seconds) - (minute * 60) - (hour * 60 * 60) - (day * 24 * 60 * 60)
|
// 如果小于0在前面进行补0操作
|
showHour = this.$t.number.formatNumberAddZero(showHour)
|
minute = this.$t.number.formatNumberAddZero(minute)
|
second = this.$t.number.formatNumberAddZero(second)
|
day = this.$t.number.formatNumberAddZero(day)
|
|
this.d = day
|
this.h = showHour
|
this.m = minute
|
this.s = second
|
},
|
// 倒计时结束
|
end() {
|
this.clearTimer()
|
this.$emit('end')
|
},
|
// 清除倒计时
|
clearTimer() {
|
if (this.timer !== null) {
|
clearInterval(this.timer)
|
this.timer = null
|
}
|
}
|
}
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
|
.tn-countdown {
|
/* #ifndef APP-NVUE */
|
display: inline-flex;
|
/* #endif */
|
align-items: center;
|
|
&__item {
|
box-sizing: content-box;
|
display: flex;
|
flex-direction: row;
|
align-items: center;
|
justify-content: center;
|
padding: 2rpx;
|
border-radius: 6rpx;
|
white-space: nowrap;
|
transform: translateZ(0);
|
|
&__time {
|
margin: 0;
|
padding: 0;
|
line-height: 1;
|
}
|
}
|
|
&__separator {
|
display: flex;
|
flex-direction: row;
|
align-items: center;
|
justify-content: center;
|
padding: 0 5rpx;
|
line-height: 1;
|
}
|
}
|
</style>
|