315 lines
7.9 KiB
Vue
315 lines
7.9 KiB
Vue
<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.$tn.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.$tn.number.formatNumberAddZero(showHour)
|
||
minute = this.$tn.number.formatNumberAddZero(minute)
|
||
second = this.$tn.number.formatNumberAddZero(second)
|
||
day = this.$tn.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>
|