这个模块功能上线是在前两个月,今天打开群一看,说倒计时有bug。当剩余时间为一天的时候就会出现0天0时0分。
实现思路,和网上大多数都很相似,直接拎出来不解释了。
<template>
<div>
<div class="countDown" v-if="type == 1">{{ `${day}天${hr}:${min}:${sec}` }}</div>
<div class="countDown" v-else-if="type == 2">
<span class="task_time">{{ day }}</span>
<span>天</span>
<span class="task_time">{{ hr }}</span>
<span>时</span>
<span class="task_time">{{ min }}</span>
<span>分</span>
<span class="task_time">{{ sec }}</span>
<span>后截止</span>
</div>
<div class="countDown" v-else-if="type == 3">{{ `${day}天 ${hr}小时 ${min}分 ${sec}秒` }}</div>
<div class="countDown no_background" v-else-if="type == 4">{{ `${day}天${hr}:${min}:${sec}` }}</div>
</div>
</template>
<script>
import moment from 'moment'
//倒计时 子组件,设定 三天之内显示倒计时,开始时间 + 到期时间 - 当前时间 = 倒计时
export default {
name: 'count-down',
props: {
start: {
type: String,
default: '2023-10-15 19:31:00'
},
end: {
type: String,
default: '2023-10-16 19:31:00'
},
duration: {
type: Number,
default: 72 * 60 * 60 * 1000
},
type: {
type: [Number, String],
default: 1
}
},
mounted () {
this.countdown()
},
destroyed () {
clearTimeout(this.timer)
},
methods: {
countdown () {
let start = moment(this.start).format('YYYY-MM-DD HH:mm:ss');
console.log('start:', start)
// const end = Date.parse(new Date(start)) + this.duration
// const now = Date.parse(new Date())
const end = new Date(start).getTime() + this.duration;
console.log('end:', end)
const now = Date.now();
console.log('now:', now)
const msec = end - now
console.log('msec:', msec)
if (msec <= 0) {
this.day = 0
this.hr = 0
this.min = 0
this.sec = 0
clearTimeout(this.timer)
return
}
// let day = parseInt(msec / 1000 / 60 / 60 / 24)
// let hr = parseInt(msec / 1000 / 60 / 60 % 24)
// let min = parseInt(msec / 1000 / 60 % 60)
// let sec = parseInt(msec / 1000 % 60)
let day = Math.floor(msec / (1000 * 60 * 60 * 24));
let hr = Math.floor((msec / (1000 * 60 * 60)) % 24);
let min = Math.floor((msec / (1000 * 60)) % 60);
let sec = Math.floor((msec / 1000) % 60);
this.day = day
this.hr = hr > 9 ? hr : '0' + hr
this.min = min > 9 ? min : '0' + min
this.sec = sec > 9 ? sec : '0' + sec
this.timer = setTimeout(() => {
this.countdown()
}, 1000)
},
},
data () {
return {
timer: null,
day: '',
hr: '',
min: '',
sec: ''
}
}
}
</script>
<style lang="scss" scoped>
.countDown {
text-align: center;
background: linear-gradient(90deg, #FFE6E6 0%, rgba(255,230,230,0) 100%);
border-radius: 4px 0px 0px 4px;
span {
font-size: 12px;
font-family: SourceHanSansSC-Regular, SourceHanSansSC;
font-weight: 400;
color: #f87474;
}
.task_time {
border-radius: 2px;
color: #FFFFFF;
padding: 0 2px;
background-color: #f54646;
}
}
.no_background {
background: transparent;
color: #E53232;
}
</style>
组件封装的没啥大问题,倒计时天数的逻辑也对。问题出现在,调用时候的duration传值。
假如显示三天之内的倒计时,需要判断剩余天数是否小于等于2同时还要计算时、分、 秒是大于还是小于和等于0。这块计算难度就增加了,额外增加工作量。当时匆忙上线,没考虑那么多逻辑,大家引以为戒避免返工。
后端传值
"residue_days": 1,
"residue_hours": 5,
"residue_minutes": 36,
"end_time": "2024-01-18T17:47:00",
"created_at": "2024-01-06T17:47:38",
第二种:既然有了开始时间和结束时间,就直接传值,要显示三天内倒计时就用v-if/v-show判断 residue_days <= 2。
countdown() {
// 假设 start 和 end 是已经定义好的日期字符串
// 使用 moment.js 处理和转换时间
// 注意:这假设您的环境中已经安装并引入了 moment.js
let startMoment = moment(this.start);
let endMoment = moment(this.end);
// 计算结束时间和当前时间的差异
let now = moment(); // 当前时间
let duration = endMoment.diff(now); // 使用 moment.js 的 diff 函数来获取毫秒差
// 进行倒计时
if (duration <= 0) {
// 倒计时已结束
this.day = 0
this.hr = 0
this.min = 0
this.sec = 0
// 清理定时器并进行后续处理
clearTimeout(this.timer);
return
} else {
// 更新倒计时时间
// 注意:以下的时间单位计算使用了向下取整 Math.floor 方法,
// 因为我们想要获得完整的小时、分钟或者秒数
let day = Math.floor(duration / (1000 * 60 * 60 * 24));
let hr = Math.floor((duration / (1000 * 60 * 60)) % 24);
let min = Math.floor((duration / (1000 * 60)) % 60);
let sec = Math.floor((duration / 1000) % 60);
// 更新倒计时显示
this.day = day;
this.hr = hr < 10 ? '0' + hr : hr;
this.min = min < 10 ? '0' + min : min;
this.sec = sec < 10 ? '0' + sec : sec;
// 递归调用以更新倒计时
this.timer = setTimeout(() => {
this.countdown();
}, 1000);
}
}