Vue.js倒计时器:按9小时工作日计算截止时间需求
Vue.js 工作日倒计时器(按每日9小时计算)
以下是修改后的完整代码,实现了按**每日9小时工作日(上午9点至下午6点)**计算截止时间的逻辑,满足18小时对应2个工作日、20小时对应2个工作日加2小时的需求:
修改后的JavaScript代码
var application = new Vue({ data: { countdownData: { startDateTime: null, startHour: 9, endHour: 18, tenure: 1, time: { total: 0, days: 0, hours: 0, minutes: 0, seconds: 0, }, deadline: null, paused: false, timeLeft: 0, timeInterval: null, countdownActive: false, offDays: 0, }, }, filters: { formatDate: function (value) { if (value) { const options = { year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric' }; return new Date(value).toLocaleDateString('zh-CN', options); } return ''; }, }, methods: { timeRemaining(endtime) { const t = Date.parse(endtime) - Date.now(); const seconds = Math.floor((t / 1000) % 60); const minutes = Math.floor((t / 1000 / 60) % 60); const hours = Math.floor((t / (1000 * 60 * 60)) % 24); const days = Math.floor(t / (1000 * 60 * 60 * 24)); return { total: t, days, hours, minutes, seconds }; }, runClock() { this.updateClock(); this.countdownData.timeInterval = setInterval(this.updateClock, 1000); }, updateClock() { const currentTime = new Date(); const isWithinWorkingHours = currentTime.getHours() >= this.countdownData.startHour && currentTime.getHours() < this.countdownData.endHour; if (isWithinWorkingHours) { this.countdownData.countdownActive = true; this.countdownData.time = this.timeRemaining( this.countdownData.deadline ); if (this.countdownData.time.total <= 0) { clearInterval(this.countdownData.timeInterval); } } else { this.stopClock(); this.countdownData.countdownActive = false; } }, pauseClock() { if (!this.countdownData.paused) { this.countdownData.paused = true; clearInterval(this.countdownData.timeInterval); this.countdownData.timeLeft = this.countdownData.time.total; } }, resumeClock() { if (this.countdownData.paused) { this.countdownData.paused = false; this.countdownData.deadline = new Date( Date.now() + this.countdownData.timeLeft ); this.runClock(); } }, handleInput() { this.stopClock(); this.countdownData.deadline = this.calculateDeadline(); this.runClock(); }, stopClock() { clearInterval(this.countdownData.timeInterval); }, calculateDeadline() { if (!this.countdownData.startDateTime) return null; const start = new Date(this.countdownData.startDateTime); let remainingHours = this.countdownData.tenure; const workHoursPerDay = this.countdownData.endHour - this.countdownData.startHour; let currentDate = new Date(start); // 处理起始时间不在工作时段的情况 const isStartInWorkHours = currentDate.getHours() >= this.countdownData.startHour && currentDate.getHours() < this.countdownData.endHour; if (!isStartInWorkHours) { if (currentDate.getHours() < this.countdownData.startHour) { // 早于上班时间,跳到当天上班点 currentDate.setHours(this.countdownData.startHour, 0, 0, 0); } else { // 晚于下班时间,跳到下一个工作日(含休息日)的上班点 currentDate.setDate(currentDate.getDate() + 1 + this.countdownData.offDays); currentDate.setHours(this.countdownData.startHour, 0, 0, 0); } } // 逐天消耗剩余时长 while (remainingHours > 0) { const todayEnd = new Date(currentDate); todayEnd.setHours(this.countdownData.endHour, 0, 0, 0); const remainingTodayHours = (todayEnd - currentDate) / (1000 * 60 * 60); if (remainingHours <= remainingTodayHours) { // 剩余时长可在当天完成 currentDate.setHours(currentDate.getHours() + remainingHours); remainingHours = 0; } else { // 消耗当日剩余时间,跳转到下一个工作日 remainingHours -= remainingTodayHours; currentDate.setDate(currentDate.getDate() + 1 + this.countdownData.offDays); currentDate.setHours(this.countdownData.startHour, 0, 0, 0); } } return currentDate; }, }, beforeDestroy() { this.stopClock(); }, mounted() { this.handleInput(); }, }).$mount('#app');
HTML代码(适配中文显示)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <table class="table table-bordered"> <tbody> <tr> <td> <label for="startDateTimeInput">输入开始日期时间:</label> <input type="datetime-local" id="startDateTimeInput" v-model="countdownData.startDateTime" @input="handleInput" class="form-control" /> </td> <td> <label for="tenureInput">输入时长(小时):</label> <input type="number" id="tenureInput" v-model="countdownData.tenure" @input="handleInput" class="form-control" min="1" /> </td> <td> <label for="offDaysInput">输入休息日天数:</label> <input type="number" id="offDaysInput" v-model="countdownData.offDays" @input="handleInput" class="form-control" min="0" /> </td> </tr> </tbody> </table> <div v-if="countdownData.countdownActive"> <div class="mx-auto" id="clockdiv"> <h2 class="text-center text-danger">{{ countdownData.time.hours }}: {{ countdownData.time.minutes }} :{{ countdownData.time.seconds }}</h2> </div> <div class="text-center"> <p>截止时间: {{ countdownData.deadline | formatDate }}</p> </div> <div class="d-flex justify-content-center"> <button class="btn btn-primary mr-2" type="button" @click="pauseClock">暂停</button> <button class="btn btn-primary" type="button" @click="resumeClock">继续</button> </div> </div> <div v-else> <p>倒计时仅在工作时段内激活。</p> </div> </div>
关键修改说明
- 核心逻辑重写:完全重构
calculateDeadline方法,实现工作日时长计算规则,自动处理起始时间不在工作时段的情况,逐天消耗剩余时长并跳过休息日 - 本地化适配:将日期显示改为中文格式,更符合国内使用习惯
- 功能兼容:保留原有暂停/继续、实时倒计时更新等功能,仅修改截止时间计算逻辑
内容的提问来源于stack exchange,提问作者rahi bd
相关产品推荐
相关产品推荐

