|
@@ -0,0 +1,206 @@
|
|
|
+import { defineComponent, ref, watch, nextTick, onMounted } from 'vue';
|
|
|
+import styles from '../index.module.less';
|
|
|
+import { NTabs, NTabPane, NSpace, NButton, NImage, NInput, NInputNumber } from 'naive-ui';
|
|
|
+import { useRoute } from 'vue-router';
|
|
|
+import Flipper from '../modals/flipper.vue'
|
|
|
+import { stringify } from 'crypto-js/enc-utf8';
|
|
|
+import dayjs from 'dayjs';
|
|
|
+import playIcon from '../images/playing.png'
|
|
|
+import suspend from '../images/suspend.png'
|
|
|
+import add from '../images/add.png'
|
|
|
+import minus from '../images/minus.png'
|
|
|
+import { getSecond } from '@/utils/index'
|
|
|
+export default defineComponent({
|
|
|
+ name: 'timer-countdown',
|
|
|
+ setup() {
|
|
|
+ const activeTab = ref('positive'); //countdown
|
|
|
+ const route = useRoute();
|
|
|
+ // const flipperHour1 = ref()
|
|
|
+ // const flipperHour2 = ref()
|
|
|
+ const flipperMinute1 = ref()
|
|
|
+ const flipperMinute2 = ref()
|
|
|
+ const flipperSecond1 = ref()
|
|
|
+ const flipperSecond2 = ref()
|
|
|
+ const timer = ref(null as any)
|
|
|
+ const nowTimer = ref(null) as any
|
|
|
+ const nowDate = ref(new Date) as any
|
|
|
+ nowTimer.value = setInterval(() => {
|
|
|
+ nowDate.value = new Date()
|
|
|
+ }, 1000)
|
|
|
+ const count = ref(0)
|
|
|
+ const mine = ref(0)
|
|
|
+ const second = ref(0)
|
|
|
+ const isPlaying = ref(false)
|
|
|
+ // flipperHour1, flipperHour2,
|
|
|
+ const flipObjs = ref([flipperMinute1, flipperMinute2, flipperSecond1, flipperSecond2]) as any
|
|
|
+ const init = () => {
|
|
|
+ const now = new Date()
|
|
|
+ const nowTimeStr = '0000'
|
|
|
+
|
|
|
+ for (let i = 0; i < flipObjs.value.length; i++) {
|
|
|
+ flipObjs.value[i].value.setFront(nowTimeStr[i])
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const formatDate = (date: Date, dateFormat: string) => {
|
|
|
+ /* 单独格式化年份,根据y的字符数量输出年份
|
|
|
+ * 例如:yyyy => 2019
|
|
|
+ yy => 19
|
|
|
+ y => 9
|
|
|
+ */
|
|
|
+ if (/(y+)/.test(dateFormat)) {
|
|
|
+ dateFormat = dateFormat.replace(
|
|
|
+ RegExp.$1,
|
|
|
+ (date.getFullYear() + '').substr(4 - RegExp.$1.length)
|
|
|
+ )
|
|
|
+ }
|
|
|
+ // 格式化月、日、时、分、秒
|
|
|
+ const o = {
|
|
|
+ 'm+': date.getMonth() + 1,
|
|
|
+ 'd+': date.getDate(),
|
|
|
+ 'h+': date.getHours(),
|
|
|
+ 'i+': date.getMinutes(),
|
|
|
+ 's+': date.getSeconds()
|
|
|
+ } as any
|
|
|
+ for (const k in o) {
|
|
|
+ if (new RegExp(`(${k})`).test(dateFormat)) {
|
|
|
+ // 取出对应的值
|
|
|
+ const str = o[k] + ''
|
|
|
+ /* 根据设置的格式,输出对应的字符
|
|
|
+ * 例如: 早上8时,hh => 08,h => 8
|
|
|
+ * 但是,当数字>=10时,无论格式为一位还是多位,不做截取,这是与年份格式化不一致的地方
|
|
|
+ * 例如: 下午15时,hh => 15, h => 15
|
|
|
+ */
|
|
|
+ dateFormat = dateFormat.replace(
|
|
|
+ RegExp.$1,
|
|
|
+ RegExp.$1.length === 1 ? str : padLeftZero(str)
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return dateFormat
|
|
|
+ }
|
|
|
+ const padLeftZero = (str: string) => {
|
|
|
+ return ('00' + str).substr(str.length)
|
|
|
+ }
|
|
|
+
|
|
|
+ const run = () => {
|
|
|
+ timer.value = setInterval(() => {
|
|
|
+ // 获取当前时间
|
|
|
+ const now = new Date()
|
|
|
+ const nowTimeStr = formatDate(new Date(now.getTime() - 1000), 'iiss')
|
|
|
+ const nextTimeStr = formatDate(now, 'iiss')
|
|
|
+ console.log(nowTimeStr, nextTimeStr)
|
|
|
+ for (let i = 0; i < flipObjs.value.length; i++) {
|
|
|
+ if (nowTimeStr[i] === nextTimeStr[i]) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ flipObjs.value[i].value.flipDown(
|
|
|
+ nowTimeStr[i],
|
|
|
+ nextTimeStr[i]
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }, 1000)
|
|
|
+
|
|
|
+ }
|
|
|
+ const startTimer = () => {
|
|
|
+ isPlaying.value = true;
|
|
|
+ timer.value = setInterval(() => {
|
|
|
+ // 获取当前时间
|
|
|
+ const lastStr = getSecond(count.value)
|
|
|
+ count.value++
|
|
|
+
|
|
|
+ const str = getSecond(count.value)
|
|
|
+ for (let i = 0; i < flipObjs.value.length; i++) {
|
|
|
+ if (lastStr[i] === str[i]) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ flipObjs.value[i].value.flipDown(lastStr[i], str[i])
|
|
|
+ }
|
|
|
+ }, 1000)
|
|
|
+ }
|
|
|
+
|
|
|
+ const suspendNum = () => {
|
|
|
+ isPlaying.value = false;
|
|
|
+ if (timer.value) {
|
|
|
+ clearInterval(timer.value)
|
|
|
+ timer.value = null
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const onReset = () => {
|
|
|
+
|
|
|
+ suspendNum()
|
|
|
+ nextTick(() => {
|
|
|
+ count.value = 0
|
|
|
+ init()
|
|
|
+ })
|
|
|
+
|
|
|
+ }
|
|
|
+ onMounted(() => {
|
|
|
+ nextTick(() => {
|
|
|
+ init()
|
|
|
+ // run()
|
|
|
+ })
|
|
|
+
|
|
|
+ })
|
|
|
+
|
|
|
+ return () => (
|
|
|
+ <div class={styles.timerItemWrap}>
|
|
|
+ dao
|
|
|
+ <div class={styles.timerItemInfo}>
|
|
|
+ <div class={styles.timerItemInset}>
|
|
|
+ <div class={styles.timerItemInfoTop}>
|
|
|
+ <div class={styles.timerItemTopCore}>
|
|
|
+ <h4> 分</h4>
|
|
|
+
|
|
|
+ <div class={styles.FlipClock}>
|
|
|
+ <Flipper ref={flipperMinute1} />
|
|
|
+ <Flipper ref={flipperMinute2} />
|
|
|
+ <div class={styles.chioseWrap}>
|
|
|
+ <img src={add} class={styles.add} alt="" />
|
|
|
+ <NInputNumber class={styles.countInput} min={0} max={59} show-button={false} v-model:value={mine.value}></NInputNumber>
|
|
|
+ <img src={minus} class={styles.minus} alt="" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class={styles.timerItemTopCore}>
|
|
|
+ <h4 class={styles.dotTop}></h4>
|
|
|
+ <div class={styles.dot}></div>
|
|
|
+ <div class={styles.dot}></div>
|
|
|
+ </div>
|
|
|
+ <div class={styles.timerItemTopCore}>
|
|
|
+ <h4> 秒 </h4>
|
|
|
+ <div class={styles.FlipClock}>
|
|
|
+ <Flipper ref={flipperSecond1} />
|
|
|
+ <Flipper ref={flipperSecond2} />
|
|
|
+ <div class={styles.chioseWrap}>
|
|
|
+ <img src={add} class={styles.add} alt="" />
|
|
|
+ <NInputNumber class={styles.countInput} min={0} max={59} show-button={false} v-model:value={second.value}></NInputNumber>
|
|
|
+ <img src={minus} class={styles.minus} alt="" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <NSpace class={styles.btnGroupModal} justify="center">
|
|
|
+ <NButton round onClick={() => onReset()}>
|
|
|
+ 重置
|
|
|
+ </NButton>
|
|
|
+ {isPlaying.value ? <NButton round type="primary" icon-placement="right" onClick={() => suspendNum()} v-slots={{
|
|
|
+ default: () => <>暂停</>,
|
|
|
+ icon: () => <NImage previewDisabled class={styles.palyIcon} src={suspend}></NImage>
|
|
|
+ }}>
|
|
|
+
|
|
|
+ </NButton> : <NButton round type="primary" icon-placement="right" onClick={() => startTimer()} v-slots={{
|
|
|
+ default: () => <>开始</>,
|
|
|
+ icon: () => <NImage previewDisabled class={styles.palyIcon} src={playIcon}></NImage>
|
|
|
+ }}>
|
|
|
+ </NButton>}
|
|
|
+
|
|
|
+ </NSpace>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+});
|