<template>
<view class="u-countdown">
<view class="u-countdown-item" :style="[itemStyle]" v-if="showDays && (hideZeroDay || (!hideZeroDay && d != '0'))">
<view class="u-countdown-time" :style="[letterStyle]">
{{ d }}
</view>
</view>
<view
class="u-countdown-colon"
:style="{fontSize: separatorSize + 'rpx', color: separatorColor, paddingBottom: separator == 'colon' ? '4rpx' : 0}"
v-if="showDays && (hideZeroDay || (!hideZeroDay && d != '0'))"
>
{{ separator == 'colon' ? ':' : '天' }}
</view>
<view class="u-countdown-item" :style="[itemStyle]" v-if="showHours">
<view class="u-countdown-time" :style="{ fontSize: fontSize + 'rpx', color: color}">
{{ h }}
</view>
</view>
<view
class="u-countdown-colon"
:style="{fontSize: separatorSize + 'rpx', color: separatorColor, paddingBottom: separator == 'colon' ? '4rpx' : 0}"
v-if="showHours"
>
{{ separator == 'colon' ? ':' : '时' }}
</view>
<view class="u-countdown-item" :style="[itemStyle]" v-if="showMinutes">
<view class="u-countdown-time" :style="{ fontSize: fontSize + 'rpx', color: color}">
{{ i }}
</view>
</view>
<view
class="u-countdown-colon"
:style="{fontSize: separatorSize + 'rpx', color: separatorColor, paddingBottom: separator == 'colon' ? '4rpx' : 0}"
v-if="showMinutes"
>
{{ separator == 'colon' ? ':' : '分' }}
</view>
<view class="u-countdown-item" :style="[itemStyle]" v-if="showSeconds">
<view class="u-countdown-time" :style="{ fontSize: fontSize + 'rpx', color: color}">
{{ s }}
</view>
</view>
<view
class="u-countdown-colon"
:style="{fontSize: separatorSize + 'rpx', color: separatorColor, paddingBottom: separator == 'colon' ? '4rpx' : 0}"
v-if="showSeconds && separator == 'zh'"
>
秒
</view>
</view>
</template>
<script>
export default {
name: 'u-count-down',
props: {
timestamp: {
type: [Number, String],
default: 0
},
autoplay: {
type: Boolean,
default: true
},
separator: {
type: String,
default: 'colon'
},
separatorSize: {
type: [Number, String],
default: 30
},
separatorColor: {
type: String,
default: "#303133"
},
color: {
type: String,
default: '#303133'
},
fontSize: {
type: [Number, String],
default: 30
},
bgColor: {
type: String,
default: '#fff'
},
height: {
type: [Number, String],
default: 'auto'
},
showBorder: {
type: Boolean,
default: false
},
borderColor: {
type: String,
default: '#303133'
},
showSeconds: {
type: Boolean,
default: true
},
showMinutes: {
type: Boolean,
default: true
},
showHours: {
type: Boolean,
default: true
},
showDays: {
type: Boolean,
default: true
},
hideZeroDay: {
type: Boolean,
default: false
}
},
watch: {
timestamp(newVal, oldVal) {
clearInterval(this.timer);
this.start();
}
},
data() {
return {
d: '00',
h: '00',
i: '00',
s: '00',
timer: null ,
seconds: 0,
};
},
computed: {
itemStyle() {
let style = {};
if(this.height) {
style.height = this.height + 'rpx';
style.width = this.height + 'rpx';
}
if(this.showBorder) {
style.borderStyle = 'solid';
style.borderColor = this.borderColor;
style.borderWidth = '1px';
}
if(this.bgColor) {
style.backgroundColor = this.bgColor;
}
return style;
},
letterStyle() {
let style = {};
if(this.fontSize) style.fontSize = this.fontSize + 'rpx';
if(this.color) style.color = this.color;
return style;
}
},
mounted() {
this.autoplay && this.timestamp && this.start();
},
methods: {
start() {
if (this.timestamp <= 0) return;
this.seconds = Number(this.timestamp);
this.formatTime(this.seconds);
this.timer = setInterval(() => {
this.seconds--;
this.$emit('change', this.seconds);
if (this.seconds < 0) {
return this.end();
}
this.formatTime(this.seconds);
}, 1000);
},
formatTime(seconds) {
seconds <= 0 && this.end();
let [day, hour, minute, second] = [0, 0, 0, 0];
day = Math.floor(seconds / (60 * 60 * 24));
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) - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60;
showHour = showHour < 10 ? '0' + showHour : showHour;
minute = minute < 10 ? '0' + minute : minute;
second = second < 10 ? '0' + second : second;
this.d = day;
this.h = showHour;
this.i = minute;
this.s = second;
},
end() {
clearInterval(this.timer);
this.timer = null;
this.$emit('end', {});
}
},
beforeDestroy() {
clearInterval(this.timer);
this.timer = null;
}
};
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
.u-countdown {
display: inline-flex;
align-items: center;
}
.u-countdown-item {
display: flex;
align-items: center;
justify-content: center;
padding: 2rpx;
border-radius: 6rpx;
white-space: nowrap;
transform: translateZ(0);
}
.u-countdown-time {
margin: 0;
padding: 0;
line-height: 1;
}
.u-countdown-colon {
display: flex;
justify-content: center;
padding: 0 5rpx;
line-height: 1;
align-items: center;
padding-bottom: 4rpx;
}
.u-countdown-scale {
transform: scale(0.9);
transform-origin: center center;
}
</style>