<template>
  <div class='countdown'>
    <div class='input-container'>
      <label for='time-input'>倒计时时间(分钟):</label>
      <input type='number' id='time-input' v-model='time' min='1' max='1440' />
    </div>
    <div class='button-container'>
      <div class='start-button' :class="{ disabled: isCounting }" @click='startCountdown'>开始</div>
      <div class='pause-button' :class="{ disabled: !isCounting }" @click='pauseCountdown'>暂停</div>
      <div class='reset-button' :class="{ disabled: isCounting }" @click='resetCountdown'>重置</div>
    </div>
    <div class='time-display'>{{ displayTime }}</div>
    <div class='learn-time'>您的学习时长为:{{ learntime }}分钟</div>
  </div>
</template>
<script>
export default {
  name: "EffectiveLearning",
  data() {
    return {
      time: 0,
      isCounting: false,
      countdownInterval: null,
      startTime: null,
      elapsedTime: 0,
      visibilityChangeHandler: null,
      leaveTimestamp: null,
      backTimestamp: null,
      learntime: 0
    };
  },
  computed: {
    displayTime() {
      const remainingTime = this.time * 60 - this.elapsedTime;
      const minutes = Math.floor(remainingTime / 60);
      const seconds = remainingTime % 60;
      return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
    }
  },
  methods: {
    startCountdown() {
      if (this.time === 0 || this.isCounting) {
        return;
      }
      this.isCounting = true;
      this.startTime = Date.now() - this.elapsedTime * 1000;
      this.countdownInterval = setInterval(() => {
        this.elapsedTime = Math.floor((Date.now() - this.startTime) / 1000);
        if (this.elapsedTime >= this.time * 60) {
          this.pauseCountdown();
          const totalTime = (this.backTimestamp - this.leaveTimestamp) / 1000 / 60;
          this.learntime = Math.floor(Math.max(0, this.time - totalTime));
          this.returntimme();
        }
      }, 1000);
      this.visibilityChangeHandler = () => {
        if (document.visibilityState === 'hidden') {
          this.pauseCountdown();
          this.leaveTimestamp = Date.now();
        } else if (document.visibilityState === 'visible' && this.isCounting) {
          this.startCountdown();
          this.backTimestamp = Date.now();
        }
      };
      document.addEventListener('visibilitychange', this.visibilityChangeHandler);
    },
    pauseCountdown() {
      if (!this.isCounting) {
        return;
      }
      clearInterval(this.countdownInterval);
      this.countdownInterval = null;
      this.isCounting = false;
    },
    returntimme() {
      console.log('1')
      this.$net.post('/Study/learnandleavetime', { learntime: this.learntime }).then(resp => {
        if (resp.data.code === 200) {

        } else {
          alert('保存失败')
        }
      }).catch(error => {
        console.log(error)
        alert('保存失败')
      })
    },
    resetCountdown() {
      if (this.isCounting) {
        return;
      }
      this.time = 0;
      this.elapsedTime = 0;
      this.learntime = 0;
      this.leaveTimestamp = null;
      this.backTimestamp = null;
    }
  },
  watch: {
    time() {
      if (!this.isCounting) {
        this.elapsedTime = 0;
        this.learntime = 0;
      }
    }
  },
  beforeUnmount() {
    document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
  },
  created() {
    window.addEventListener('focus', this.startCountdown);
    window.addEventListener('blur', this.pauseCountdown);
  },
  beforeUnmount() {
    window.removeEventListener('focus', this.startCountdown);
    window.removeEventListener('blur', this.pauseCountdown);
    document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
  }
};
</script>
<style>
.countdown {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
}

.input-container {
  margin-bottom: 20px;
}

.button-container {
  display: flex;
  justify-content: center;
  margin-bottom: 20px;
}

.start-button,
.pause-button,
.reset-button {
  display: inline-block;
  padding: 10px 20px;
  margin: 0 10px;
  border: 1px solid #ccc;
  border-radius: 5px;
  cursor: pointer;
}

.start-button.disabled,
.reset-button.disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.pause-button.disabled {
  border-color: #ccc;
  color: #ccc;
  cursor: not-allowed;
}

.time-display {
  font-size: 48px;
}

.learn-time {
  margin-top: 20px;
  font-size: 24px;
}
</styl
网页可见性监听计时器:记录用户离开和返回页面时间并计算学习时长

原文地址: https://www.cveoy.top/t/topic/mCjN 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录